mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 13:20:43 +00:00
QQQ-41: added app sections, wired all dashboards, implemented widgets that could be, upped version
This commit is contained in:
@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import {Alert} from "@mui/material";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
@ -30,7 +30,7 @@ import Grid from "@mui/material/Grid";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import {Form, Formik} from "formik";
|
||||
import React, {useReducer, useState} from "react";
|
||||
import {useParams, useNavigate, useLocation} from "react-router-dom";
|
||||
import {useLocation, useNavigate, useParams} from "react-router-dom";
|
||||
import * as Yup from "yup";
|
||||
import {QCancelButton, QSaveButton} from "qqq/components/QButtons";
|
||||
import QDynamicForm from "qqq/components/QDynamicForm";
|
||||
@ -58,7 +58,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
||||
const [initialValues, setInitialValues] = useState({} as { [key: string]: string });
|
||||
const [formFields, setFormFields] = useState(null as Map<string, any>);
|
||||
const [t1sectionName, setT1SectionName] = useState(null as string);
|
||||
const [nonT1Sections, setNonT1Sections] = useState([] as QSection[]);
|
||||
const [nonT1Sections, setNonT1Sections] = useState([] as QTableSection[]);
|
||||
|
||||
const [alertContent, setAlertContent] = useState("");
|
||||
|
||||
@ -66,7 +66,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
||||
const [formValues, setFormValues] = useState({} as { [key: string]: string });
|
||||
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
|
||||
const [record, setRecord] = useState(null as QRecord);
|
||||
const [tableSections, setTableSections] = useState(null as QSection[]);
|
||||
const [tableSections, setTableSections] = useState(null as QTableSection[]);
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -144,7 +144,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
||||
/////////////////////////////////////
|
||||
const dynamicFormFieldsBySection = new Map<string, any>();
|
||||
let t1sectionName;
|
||||
const nonT1Sections: QSection[] = [];
|
||||
const nonT1Sections: QTableSection[] = [];
|
||||
for (let i = 0; i < tableSections.length; i++)
|
||||
{
|
||||
const section = tableSections[i];
|
||||
@ -325,7 +325,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
||||
}
|
||||
</Card>
|
||||
</MDBox>
|
||||
{formFields && nonT1Sections.length ? nonT1Sections.map((section: QSection) => (
|
||||
{formFields && nonT1Sections.length ? nonT1Sections.map((section: QTableSection) => (
|
||||
<MDBox key={`edit-card-${section.name}`} pb={3}>
|
||||
<Card id={section.name} sx={{overflow: "visible"}}>
|
||||
<MDTypography variant="h5" p={3} pb={1}>
|
||||
|
@ -26,16 +26,18 @@ import {ReactNode} from "react";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import MDTypography from "qqq/components/Temporary/MDTypography";
|
||||
|
||||
interface Props {
|
||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
||||
title: string;
|
||||
percentage?: {
|
||||
color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark" | "white";
|
||||
amount: string | number;
|
||||
label: string;
|
||||
};
|
||||
icon: ReactNode;
|
||||
[key: string]: any;
|
||||
interface Props
|
||||
{
|
||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
||||
title: string;
|
||||
percentage?: {
|
||||
color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark" | "white";
|
||||
amount: string | number;
|
||||
label: string;
|
||||
};
|
||||
icon: ReactNode;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function ProcessLinkCard({
|
||||
@ -44,7 +46,7 @@ function ProcessLinkCard({
|
||||
{
|
||||
return (
|
||||
<Card>
|
||||
<MDBox display="flex" justifyContent="space-between" pt={1} px={2}>
|
||||
<MDBox display="flex" justifyContent="space-between" pt={3} px={2}>
|
||||
<MDBox
|
||||
variant="gradient"
|
||||
bgColor={color}
|
||||
|
@ -26,12 +26,14 @@ import {Link} from "react-router-dom";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import MDTypography from "qqq/components/Temporary/MDTypography";
|
||||
|
||||
interface Props {
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
route: string | string[];
|
||||
light?: boolean;
|
||||
[key: string]: any;
|
||||
interface Props
|
||||
{
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
route: string | string[];
|
||||
light?: boolean;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const ucFirst = (input: string): string =>
|
||||
@ -107,23 +109,16 @@ function QBreadcrumbs({
|
||||
</MDTypography>
|
||||
</Link>
|
||||
))}
|
||||
<MDTypography
|
||||
variant="button"
|
||||
fontWeight="regular"
|
||||
textTransform="capitalize"
|
||||
color={light ? "white" : "dark"}
|
||||
sx={{lineHeight: 0}}
|
||||
>
|
||||
{routeToLabel(title)}
|
||||
</MDTypography>
|
||||
</MuiBreadcrumbs>
|
||||
<MDTypography
|
||||
pt={1}
|
||||
fontWeight="bold"
|
||||
textTransform="capitalize"
|
||||
variant="h6"
|
||||
variant="h5"
|
||||
color={light ? "white" : "dark"}
|
||||
noWrap
|
||||
>
|
||||
{routeToLabel(title)}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
);
|
||||
|
@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
||||
import Card from "@mui/material/Card";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import {Theme} from "@mui/material/styles";
|
||||
@ -27,8 +27,9 @@ import React from "react";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import MDTypography from "qqq/components/Temporary/MDTypography";
|
||||
|
||||
interface Props {
|
||||
tableSections: QSection[];
|
||||
interface Props
|
||||
{
|
||||
tableSections: QTableSection[];
|
||||
light?: boolean;
|
||||
}
|
||||
|
||||
@ -38,7 +39,7 @@ function QRecordSidebar({tableSections, light}: Props): JSX.Element
|
||||
<Card sx={{borderRadius: ({borders: {borderRadius}}) => borderRadius.lg, position: "sticky", top: "1%"}}>
|
||||
<MDBox component="ul" display="flex" flexDirection="column" p={2} m={0} sx={{listStyle: "none"}}>
|
||||
{
|
||||
tableSections ? tableSections.map((section: QSection, key: number) => (
|
||||
tableSections ? tableSections.map((section: QTableSection, key: number) => (
|
||||
<MDBox key={`section-${section.name}`} component="li" pt={key === 0 ? 0 : 1}>
|
||||
<MDTypography
|
||||
component="a"
|
||||
|
@ -23,11 +23,11 @@ import Divider from "@mui/material/Divider";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import Link from "@mui/material/Link";
|
||||
import List from "@mui/material/List";
|
||||
import {useEffect, useState, ReactNode, useReducer} from "react";
|
||||
import {useLocation, NavLink} from "react-router-dom";
|
||||
import {ReactNode, useEffect, useReducer, useState} from "react";
|
||||
import {NavLink, useLocation} from "react-router-dom";
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import {useMaterialUIController, setMiniSidenav, setTransparentSidenav, setWhiteSidenav,} from "context";
|
||||
import {setMiniSidenav, setTransparentSidenav, setWhiteSidenav, useMaterialUIController,} from "context";
|
||||
import sidenavLogoLabel from "examples/Sidenav/styles/sidenav";
|
||||
import AuthenticationButton from "qqq/components/Buttons/AuthenticationButton";
|
||||
import SidenavCollapse from "qqq/components/Sidenav/SidenavCollapse";
|
||||
@ -334,6 +334,12 @@ function Sidenav({color, icon, logo, companyName, routes, ...rest}: Props): JSX.
|
||||
}
|
||||
/>
|
||||
<List>{renderRoutes}</List>
|
||||
<Divider
|
||||
light={
|
||||
(!darkMode && !whiteSidenav && !transparentSidenav) ||
|
||||
(darkMode && !transparentSidenav && whiteSidenav)
|
||||
}
|
||||
/>
|
||||
<AuthenticationButton />
|
||||
</SidenavRoot>
|
||||
);
|
||||
|
65
src/qqq/components/Temporary/DataTable/DataTableBodyCell.tsx
Normal file
65
src/qqq/components/Temporary/DataTable/DataTableBodyCell.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Theme} from "@mui/material/styles";
|
||||
import {ReactNode} from "react";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
|
||||
// Declaring prop types for DataTableBodyCell
|
||||
interface Props
|
||||
{
|
||||
children: ReactNode;
|
||||
noBorder?: boolean;
|
||||
align?: "left" | "right" | "center";
|
||||
}
|
||||
|
||||
function DataTableBodyCell({noBorder, align, children}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox
|
||||
component="td"
|
||||
textAlign={align}
|
||||
py={1.5}
|
||||
px={3}
|
||||
sx={({palette: {light}, typography: {size}, borders: {borderWidth}}: Theme) => ({
|
||||
fontSize: size.sm,
|
||||
borderBottom: noBorder ? "none" : `${borderWidth[1]} solid ${light.main}`,
|
||||
})}
|
||||
>
|
||||
<MDBox
|
||||
display="inline-block"
|
||||
width="max-content"
|
||||
color="text"
|
||||
sx={{verticalAlign: "middle"}}
|
||||
>
|
||||
{children}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for DataTableBodyCell
|
||||
DataTableBodyCell.defaultProps = {
|
||||
noBorder: false,
|
||||
align: "left",
|
||||
};
|
||||
|
||||
export default DataTableBodyCell;
|
107
src/qqq/components/Temporary/DataTable/DataTableHeadCell.tsx
Normal file
107
src/qqq/components/Temporary/DataTable/DataTableHeadCell.tsx
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Icon from "@mui/material/Icon";
|
||||
import {Theme} from "@mui/material/styles";
|
||||
import {ReactNode} from "react";
|
||||
import {useMaterialUIController} from "context";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
|
||||
// Declaring props types for DataTableHeadCell
|
||||
interface Props
|
||||
{
|
||||
width?: string | number;
|
||||
children: ReactNode;
|
||||
sorted?: false | "none" | "asce" | "desc";
|
||||
align?: "left" | "right" | "center";
|
||||
}
|
||||
|
||||
function DataTableHeadCell({width, children, sorted, align, ...rest}: Props): JSX.Element
|
||||
{
|
||||
const [controller] = useMaterialUIController();
|
||||
const {darkMode} = controller;
|
||||
|
||||
return (
|
||||
<MDBox
|
||||
component="th"
|
||||
width={width}
|
||||
py={1.5}
|
||||
px={3}
|
||||
sx={({palette: {light}, borders: {borderWidth}}: Theme) => ({
|
||||
borderBottom: `${borderWidth[1]} solid ${light.main}`,
|
||||
})}
|
||||
>
|
||||
<MDBox
|
||||
{...rest}
|
||||
position="relative"
|
||||
textAlign={align}
|
||||
color={darkMode ? "white" : "secondary"}
|
||||
opacity={0.7}
|
||||
sx={({typography: {size, fontWeightBold}}: Theme) => ({
|
||||
fontSize: size.xxs,
|
||||
fontWeight: fontWeightBold,
|
||||
textTransform: "uppercase",
|
||||
cursor: sorted && "pointer",
|
||||
userSelect: sorted && "none",
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
{sorted && (
|
||||
<MDBox
|
||||
position="absolute"
|
||||
top={0}
|
||||
right={align !== "right" ? "16px" : 0}
|
||||
left={align === "right" ? "-5px" : "unset"}
|
||||
sx={({typography: {size}}: any) => ({
|
||||
fontSize: size.lg,
|
||||
})}
|
||||
>
|
||||
<MDBox
|
||||
position="absolute"
|
||||
top={-6}
|
||||
color={sorted === "asce" ? "text" : "secondary"}
|
||||
opacity={sorted === "asce" ? 1 : 0.5}
|
||||
>
|
||||
<Icon>arrow_drop_up</Icon>
|
||||
</MDBox>
|
||||
<MDBox
|
||||
position="absolute"
|
||||
top={0}
|
||||
color={sorted === "desc" ? "text" : "secondary"}
|
||||
opacity={sorted === "desc" ? 1 : 0.5}
|
||||
>
|
||||
<Icon>arrow_drop_down</Icon>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
)}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for DataTableHeadCell
|
||||
DataTableHeadCell.defaultProps = {
|
||||
width: "auto",
|
||||
sorted: "none",
|
||||
align: "left",
|
||||
};
|
||||
|
||||
export default DataTableHeadCell;
|
360
src/qqq/components/Temporary/DataTable/index.tsx
Normal file
360
src/qqq/components/Temporary/DataTable/index.tsx
Normal file
@ -0,0 +1,360 @@
|
||||
/* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Autocomplete from "@mui/material/Autocomplete";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import Table from "@mui/material/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import TableContainer from "@mui/material/TableContainer";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import parse from "html-react-parser";
|
||||
import {useEffect, useMemo, useState} from "react";
|
||||
import {useAsyncDebounce, useGlobalFilter, usePagination, useSortBy, useTable} from "react-table";
|
||||
import DefaultCell from "layouts/dashboards/sales/components/DefaultCell";
|
||||
import DataTableBodyCell from "qqq/components/Temporary/DataTable/DataTableBodyCell";
|
||||
import DataTableHeadCell from "qqq/components/Temporary/DataTable/DataTableHeadCell";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import MDInput from "qqq/components/Temporary/MDInput";
|
||||
import MDPagination from "qqq/components/Temporary/MDPagination";
|
||||
import MDTypography from "qqq/components/Temporary/MDTypography";
|
||||
import ImageCell from "qqq/pages/dashboards/Tables/ImageCell";
|
||||
|
||||
export interface TableDataInput
|
||||
{
|
||||
columns: { [key: string]: any }[];
|
||||
rows: { [key: string]: any }[];
|
||||
}
|
||||
|
||||
// Declaring props types for DataTable
|
||||
interface Props
|
||||
{
|
||||
entriesPerPage?:
|
||||
| false
|
||||
| {
|
||||
defaultValue: number;
|
||||
entries: number[];
|
||||
};
|
||||
canSearch?: boolean;
|
||||
showTotalEntries?: boolean;
|
||||
table: TableDataInput;
|
||||
pagination?: {
|
||||
variant: "contained" | "gradient";
|
||||
color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark" | "light";
|
||||
};
|
||||
isSorted?: boolean;
|
||||
noEndBorder?: boolean;
|
||||
}
|
||||
|
||||
function DataTable({
|
||||
entriesPerPage,
|
||||
canSearch,
|
||||
showTotalEntries,
|
||||
table,
|
||||
pagination,
|
||||
isSorted,
|
||||
noEndBorder,
|
||||
}: Props): JSX.Element
|
||||
{
|
||||
let defaultValue: any;
|
||||
let entries: any[];
|
||||
|
||||
if (entriesPerPage)
|
||||
{
|
||||
defaultValue = entriesPerPage.defaultValue ? entriesPerPage.defaultValue : "10";
|
||||
entries = entriesPerPage.entries ? entriesPerPage.entries : ["10", "25", "50", "100"];
|
||||
}
|
||||
|
||||
const columns = useMemo<any>(() => table.columns, [table]);
|
||||
const data = useMemo<any>(() => table.rows, [table]);
|
||||
|
||||
if (!columns || !data)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
const tableInstance = useTable(
|
||||
{columns, data, initialState: {pageIndex: 0}},
|
||||
useGlobalFilter,
|
||||
useSortBy,
|
||||
usePagination
|
||||
);
|
||||
|
||||
const {
|
||||
getTableProps,
|
||||
getTableBodyProps,
|
||||
headerGroups,
|
||||
prepareRow,
|
||||
rows,
|
||||
page,
|
||||
pageOptions,
|
||||
canPreviousPage,
|
||||
canNextPage,
|
||||
gotoPage,
|
||||
nextPage,
|
||||
previousPage,
|
||||
setPageSize,
|
||||
setGlobalFilter,
|
||||
state: {pageIndex, pageSize, globalFilter},
|
||||
}: any = tableInstance;
|
||||
|
||||
// Set the default value for the entries per page when component mounts
|
||||
useEffect(() => setPageSize(defaultValue || 10), [defaultValue]);
|
||||
|
||||
// Set the entries per page value based on the select value
|
||||
const setEntriesPerPage = (value: any) => setPageSize(value);
|
||||
|
||||
// Render the paginations
|
||||
const renderPagination = pageOptions.map((option: any) => (
|
||||
<MDPagination
|
||||
item
|
||||
key={option}
|
||||
onClick={() => gotoPage(Number(option))}
|
||||
active={pageIndex === option}
|
||||
>
|
||||
{option + 1}
|
||||
</MDPagination>
|
||||
));
|
||||
|
||||
// Handler for the input to set the pagination index
|
||||
const handleInputPagination = ({target: {value}}: any) =>
|
||||
value > pageOptions.length || value < 0 ? gotoPage(0) : gotoPage(Number(value));
|
||||
|
||||
// Customized page options starting from 1
|
||||
const customizedPageOptions = pageOptions.map((option: any) => option + 1);
|
||||
|
||||
// Setting value for the pagination input
|
||||
const handleInputPaginationValue = ({target: value}: any) => gotoPage(Number(value.value - 1));
|
||||
|
||||
// Search input value state
|
||||
const [search, setSearch] = useState(globalFilter);
|
||||
|
||||
// Search input state handle
|
||||
const onSearchChange = useAsyncDebounce((value) =>
|
||||
{
|
||||
setGlobalFilter(value || undefined);
|
||||
}, 100);
|
||||
|
||||
// A function that sets the sorted value for the table
|
||||
const setSortedValue = (column: any) =>
|
||||
{
|
||||
let sortedValue;
|
||||
|
||||
if (isSorted && column.isSorted)
|
||||
{
|
||||
sortedValue = column.isSortedDesc ? "desc" : "asce";
|
||||
}
|
||||
else if (isSorted)
|
||||
{
|
||||
sortedValue = "none";
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedValue = false;
|
||||
}
|
||||
|
||||
return sortedValue;
|
||||
};
|
||||
|
||||
// Setting the entries starting point
|
||||
const entriesStart = pageIndex === 0 ? pageIndex + 1 : pageIndex * pageSize + 1;
|
||||
|
||||
// Setting the entries ending point
|
||||
let entriesEnd;
|
||||
|
||||
if (pageIndex === 0)
|
||||
{
|
||||
entriesEnd = pageSize;
|
||||
}
|
||||
else if (pageIndex === pageOptions.length - 1)
|
||||
{
|
||||
entriesEnd = rows.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
entriesEnd = pageSize * (pageIndex + 1);
|
||||
}
|
||||
|
||||
return (
|
||||
<TableContainer sx={{boxShadow: "none"}}>
|
||||
{entriesPerPage || canSearch ? (
|
||||
<MDBox display="flex" justifyContent="space-between" alignItems="center" p={3}>
|
||||
{entriesPerPage && (
|
||||
<MDBox display="flex" alignItems="center">
|
||||
<Autocomplete
|
||||
disableClearable
|
||||
value={pageSize.toString()}
|
||||
options={entries}
|
||||
onChange={(event, newValue) =>
|
||||
{
|
||||
setEntriesPerPage(parseInt(newValue, 10));
|
||||
}}
|
||||
size="small"
|
||||
sx={{width: "5rem"}}
|
||||
renderInput={(params) => <MDInput {...params} />}
|
||||
/>
|
||||
<MDTypography variant="caption" color="secondary">
|
||||
entries per page
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
)}
|
||||
{canSearch && (
|
||||
<MDBox width="12rem" ml="auto">
|
||||
<MDInput
|
||||
placeholder="Search..."
|
||||
value={search}
|
||||
size="small"
|
||||
fullWidth
|
||||
onChange={({currentTarget}: any) =>
|
||||
{
|
||||
setSearch(search);
|
||||
onSearchChange(currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
</MDBox>
|
||||
)}
|
||||
</MDBox>
|
||||
) : null}
|
||||
<Table {...getTableProps()}>
|
||||
<MDBox component="thead">
|
||||
{headerGroups.map((headerGroup: any, i: number) => (
|
||||
<TableRow key={i} {...headerGroup.getHeaderGroupProps()}>
|
||||
{headerGroup.headers.map((column: any) => (
|
||||
column.type !== "hidden" && (
|
||||
<DataTableHeadCell
|
||||
key={i++}
|
||||
{...column.getHeaderProps(isSorted && column.getSortByToggleProps())}
|
||||
width={column.width ? column.width : "auto"}
|
||||
align={column.align ? column.align : "left"}
|
||||
sorted={setSortedValue(column)}
|
||||
>
|
||||
{column.render("header")}
|
||||
</DataTableHeadCell>
|
||||
)
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</MDBox>
|
||||
<TableBody {...getTableBodyProps()}>
|
||||
{page.map((row: any, key: any) =>
|
||||
{
|
||||
prepareRow(row);
|
||||
return (
|
||||
<TableRow key={key} {...row.getRowProps()}>
|
||||
{row.cells.map((cell: any) => (
|
||||
cell.column.type !== "hidden" && (
|
||||
<DataTableBodyCell
|
||||
key={key}
|
||||
noBorder={noEndBorder && rows.length - 1 === key}
|
||||
align={cell.column.align ? cell.column.align : "left"}
|
||||
{...cell.getCellProps()}
|
||||
>
|
||||
{
|
||||
cell.column.type === "default" && (
|
||||
cell.value && "number" === typeof cell.value ? (
|
||||
<DefaultCell>{cell.value.toLocaleString()}</DefaultCell>
|
||||
) : (<DefaultCell>{cell.render("Cell")}</DefaultCell>)
|
||||
)
|
||||
}
|
||||
{
|
||||
cell.column.type === "html" && (
|
||||
<DefaultCell>{parse(cell.value)}</DefaultCell>
|
||||
)
|
||||
}
|
||||
{
|
||||
cell.column.type === "image" && row.values["imageTotal"] && (
|
||||
<ImageCell imageUrl={row.values["imageUrl"]} label={row.values["imageLabel"]} total={row.values["imageTotal"].toLocaleString()} totalType={row.values["imageTotalType"]} />
|
||||
)
|
||||
}
|
||||
{
|
||||
cell.column.type === "image" && !row.values["imageTotal"] && (
|
||||
<ImageCell imageUrl={row.values["imageUrl"]} label={row.values["imageLabel"]} />
|
||||
)
|
||||
}
|
||||
</DataTableBodyCell>
|
||||
)
|
||||
))}
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<MDBox
|
||||
display="flex"
|
||||
flexDirection={{xs: "column", sm: "row"}}
|
||||
justifyContent="space-between"
|
||||
alignItems={{xs: "flex-start", sm: "center"}}
|
||||
p={!showTotalEntries && pageOptions.length === 1 ? 0 : 3}
|
||||
>
|
||||
{showTotalEntries && (
|
||||
<MDBox mb={{xs: 3, sm: 0}}>
|
||||
<MDTypography variant="button" color="secondary" fontWeight="regular">
|
||||
Showing {entriesStart} to {entriesEnd} of {rows.length} entries
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
)}
|
||||
{pageOptions.length > 1 && (
|
||||
<MDPagination
|
||||
variant={pagination.variant ? pagination.variant : "gradient"}
|
||||
color={pagination.color ? pagination.color : "info"}
|
||||
>
|
||||
{canPreviousPage && (
|
||||
<MDPagination item onClick={() => previousPage()}>
|
||||
<Icon sx={{fontWeight: "bold"}}>chevron_left</Icon>
|
||||
</MDPagination>
|
||||
)}
|
||||
{renderPagination.length > 6 ? (
|
||||
<MDBox width="5rem" mx={1}>
|
||||
<MDInput
|
||||
inputProps={{type: "number", min: 1, max: customizedPageOptions.length}}
|
||||
value={customizedPageOptions[pageIndex]}
|
||||
onChange={(event: any) =>
|
||||
{
|
||||
handleInputPagination(event);
|
||||
handleInputPaginationValue(event);
|
||||
}}
|
||||
/>
|
||||
</MDBox>
|
||||
) : (
|
||||
renderPagination
|
||||
)}
|
||||
{canNextPage && (
|
||||
<MDPagination item onClick={() => nextPage()}>
|
||||
<Icon sx={{fontWeight: "bold"}}>chevron_right</Icon>
|
||||
</MDPagination>
|
||||
)}
|
||||
</MDPagination>
|
||||
)}
|
||||
</MDBox>
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for DataTable
|
||||
DataTable.defaultProps = {
|
||||
entriesPerPage: {defaultValue: 10, entries: ["5", "10", "15", "20", "25"]},
|
||||
canSearch: false,
|
||||
showTotalEntries: true,
|
||||
pagination: {variant: "gradient", color: "info"},
|
||||
isSorted: true,
|
||||
noEndBorder: false,
|
||||
};
|
||||
|
||||
export default DataTable;
|
@ -26,7 +26,7 @@ import MDTypography from "components/MDTypography";
|
||||
interface Props
|
||||
{
|
||||
variant?: "gradient" | "contained";
|
||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
||||
color?: string;
|
||||
size?: "xs" | "sm" | "md" | "lg";
|
||||
badgeContent: string;
|
||||
font?:
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {styled, Theme} from "@mui/material/styles";
|
||||
import MDButton from "qqq/components/Temporary/MDButton";
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
export default styled(MDButton)(({theme, ownerState}: { theme?: Theme; ownerState: any }) =>
|
||||
{
|
||||
const {borders, functions, typography, palette} = theme;
|
||||
const {variant, paginationSize, active} = ownerState;
|
||||
|
||||
const {borderColor} = borders;
|
||||
const {pxToRem} = functions;
|
||||
const {fontWeightRegular, size: fontSize} = typography;
|
||||
const {light} = palette;
|
||||
|
||||
// width, height, minWidth and minHeight values
|
||||
let sizeValue = pxToRem(36);
|
||||
|
||||
if (paginationSize === "small")
|
||||
{
|
||||
sizeValue = pxToRem(30);
|
||||
}
|
||||
else if (paginationSize === "large")
|
||||
{
|
||||
sizeValue = pxToRem(46);
|
||||
}
|
||||
|
||||
return {
|
||||
borderColor,
|
||||
margin: `0 ${pxToRem(2)}`,
|
||||
pointerEvents: active ? "none" : "auto",
|
||||
fontWeight: fontWeightRegular,
|
||||
fontSize: fontSize.sm,
|
||||
width: sizeValue,
|
||||
minWidth: sizeValue,
|
||||
height: sizeValue,
|
||||
minHeight: sizeValue,
|
||||
|
||||
"&:hover, &:focus, &:active": {
|
||||
transform: "none",
|
||||
boxShadow: (variant !== "gradient" || variant !== "contained") && "none !important",
|
||||
opacity: "1 !important",
|
||||
},
|
||||
|
||||
"&:hover": {
|
||||
backgroundColor: light.main,
|
||||
borderColor,
|
||||
},
|
||||
};
|
||||
});
|
104
src/qqq/components/Temporary/MDPagination/index.tsx
Normal file
104
src/qqq/components/Temporary/MDPagination/index.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {createContext, FC, forwardRef, ReactNode, useContext, useMemo} from "react";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import MDPaginationItemRoot from "qqq/components/Temporary/MDPagination/MDPaginationItemRoot";
|
||||
|
||||
// The Pagination main context
|
||||
const Context = createContext<any>(null);
|
||||
|
||||
// Declare props types for MDPagination
|
||||
interface Props
|
||||
{
|
||||
item?: boolean;
|
||||
variant?: "gradient" | "contained";
|
||||
color?:
|
||||
| "white"
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "error"
|
||||
| "light"
|
||||
| "dark";
|
||||
size?: "small" | "medium" | "large";
|
||||
active?: boolean;
|
||||
children: ReactNode;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const MDPagination: FC<Props | any> = forwardRef(
|
||||
({item, variant, color, size, active, children, ...rest}, ref) =>
|
||||
{
|
||||
const context: any = useContext(Context);
|
||||
const paginationSize = context ? context.size : undefined;
|
||||
|
||||
const providerValue = useMemo(
|
||||
() => ({
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
}),
|
||||
[variant, color, size]
|
||||
);
|
||||
|
||||
return (
|
||||
<Context.Provider value={providerValue}>
|
||||
{item ? (
|
||||
<MDPaginationItemRoot
|
||||
{...rest}
|
||||
ref={ref}
|
||||
variant={active ? context.variant : "outlined"}
|
||||
color={active ? context.color : "secondary"}
|
||||
iconOnly
|
||||
circular
|
||||
ownerState={{variant, active, paginationSize}}
|
||||
>
|
||||
{children}
|
||||
</MDPaginationItemRoot>
|
||||
) : (
|
||||
<MDBox
|
||||
display="flex"
|
||||
justifyContent="flex-end"
|
||||
alignItems="center"
|
||||
sx={{listStyle: "none"}}
|
||||
>
|
||||
{children}
|
||||
</MDBox>
|
||||
)}
|
||||
</Context.Provider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Declaring default props for MDPagination
|
||||
MDPagination.defaultProps = {
|
||||
item: false,
|
||||
variant: "gradient",
|
||||
color: "info",
|
||||
size: "medium",
|
||||
active: false,
|
||||
};
|
||||
|
||||
export default MDPagination;
|
Reference in New Issue
Block a user