mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
QQQ-30: fixes from yesterday's review
This commit is contained in:
1369
package-lock.json
generated
1369
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
"@fullcalendar/interaction": "5.10.0",
|
||||
"@fullcalendar/react": "5.10.0",
|
||||
"@fullcalendar/timegrid": "5.10.0",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.2",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.3",
|
||||
"@mui/icons-material": "5.4.1",
|
||||
"@mui/material": "5.4.1",
|
||||
"@mui/styled-engine": "5.4.1",
|
||||
@ -45,13 +45,14 @@
|
||||
"react-table": "7.7.0",
|
||||
"stylis": "4.0.13",
|
||||
"stylis-plugin-rtl": "2.1.1",
|
||||
"ts-md5": "1.2.11",
|
||||
"uuid": "8.3.2",
|
||||
"web-vitals": "2.1.4",
|
||||
"yup": "0.32.11"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "react-scripts build",
|
||||
"clean": "rm -rf node_modules package-lock-bak.json",
|
||||
"clean": "rm -rf node_modules package-lock.json",
|
||||
"eject": "react-scripts eject",
|
||||
"geff-ham": "rm -rf node_modules/ && rm -rf package-lock-bak.json && npm install --legacy-peer-deps && npm start",
|
||||
"install-legacy-peer-deps": "npm install --legacy-peer-deps",
|
||||
|
29
src/App.tsx
29
src/App.tsx
@ -1,17 +1,3 @@
|
||||
/**
|
||||
=========================================================
|
||||
* Material Dashboard 2 PRO React TS - v1.0.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts
|
||||
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
|
||||
|
||||
Coded by www.creative-tim.com
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
import React, {
|
||||
useState,
|
||||
@ -48,6 +34,7 @@ import themeDark from "assets/theme-dark";
|
||||
import { useMaterialUIController, setMiniSidenav, setOpenConfigurator } from "context";
|
||||
|
||||
// Images
|
||||
import nfLogo from "assets/images/nutrifresh_one_icon_white.png";
|
||||
import brandWhite from "assets/images/logo-ct.png";
|
||||
import brandDark from "assets/images/logo-ct-dark.png";
|
||||
import EntityCreate from "./qqq/pages/entity-create";
|
||||
@ -230,11 +217,11 @@ export default function App()
|
||||
|
||||
const getRoutes = (allRoutes: any[]): any => allRoutes.map(
|
||||
(route: {
|
||||
collapse: any;
|
||||
route: string;
|
||||
component: ReactElement<any, string | JSXElementConstructor<any>>;
|
||||
key: Key;
|
||||
}) =>
|
||||
collapse: any;
|
||||
route: string;
|
||||
component: ReactElement<any, string | JSXElementConstructor<any>>;
|
||||
key: Key;
|
||||
}) =>
|
||||
{
|
||||
if (route.collapse)
|
||||
{
|
||||
@ -287,8 +274,8 @@ export default function App()
|
||||
<>
|
||||
<Sidenav
|
||||
color={sidenavColor}
|
||||
brand={(transparentSidenav && !darkMode) || whiteSidenav ? brandDark : brandWhite}
|
||||
brandName="Material Dashboard PRO"
|
||||
brand={nfLogo}
|
||||
brandName="Nutrifresh One"
|
||||
routes={routes}
|
||||
onMouseEnter={handleOnMouseEnter}
|
||||
onMouseLeave={handleOnMouseLeave}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/images/nutrifresh_one_icon.png
Normal file
BIN
src/assets/images/nutrifresh_one_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/images/nutrifresh_one_icon_white.png
Normal file
BIN
src/assets/images/nutrifresh_one_icon_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
@ -90,7 +90,7 @@ function Breadcrumbs({ icon, title, route, light }: Props): JSX.Element {
|
||||
color={light ? "white" : "dark"}
|
||||
noWrap
|
||||
>
|
||||
{title.replace("-", " ")}
|
||||
{title.replace("-", " ").replace("_", " ")}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
);
|
||||
|
@ -13,7 +13,7 @@ Coded by www.creative-tim.com
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
import { useEffect, useState, ReactNode } from "react";
|
||||
import { useEffect, useState, ReactNode, useReducer } from 'react';
|
||||
|
||||
// react-router-dom components
|
||||
import { useLocation, NavLink } from "react-router-dom";
|
||||
@ -77,6 +77,7 @@ function Sidenav({ color, brand, brandName, routes, ...rest }: Props): JSX.Eleme
|
||||
const items = pathname.split("/").slice(1);
|
||||
const itemParentName = items[1];
|
||||
const itemName = items[items.length - 1];
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
let textColor:
|
||||
| "primary"
|
||||
@ -112,10 +113,13 @@ function Sidenav({ color, brand, brandName, routes, ...rest }: Props): JSX.Eleme
|
||||
setWhiteSidenav(dispatch, window.innerWidth < 1200 ? false : whiteSidenav);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
The event listener that's calling the handleMiniSidenav function when resizing the window.
|
||||
*/
|
||||
window.addEventListener("resize", handleMiniSidenav);
|
||||
window.onload = () => {
|
||||
forceUpdate();
|
||||
};
|
||||
|
||||
// Call the handleMiniSidenav function to set the state with the initial value.
|
||||
handleMiniSidenav();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// react components
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
import React, { useReducer, useState } from "react";
|
||||
|
||||
// misc components
|
||||
@ -18,13 +18,13 @@ import Grid from "@mui/material/Grid";
|
||||
import { Alert } from "@mui/material";
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDAlert from "components/MDAlert";
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import MDButton from "../../../components/MDButton";
|
||||
|
||||
// Declaring props types for EntityForm
|
||||
interface Props {
|
||||
interface Props
|
||||
{
|
||||
id?: string;
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
const [validations, setValidations] = useState({});
|
||||
const [initialValues, setInitialValues] = useState({} as { [key: string]: string });
|
||||
const [formFields, setFormFields] = useState({});
|
||||
|
||||
const [alertContent, setAlertContent] = useState("");
|
||||
|
||||
const [asyncLoadInited, setAsyncLoadInited] = useState(false);
|
||||
@ -46,7 +47,10 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
function getDynamicStepContent(formData: any): JSX.Element
|
||||
{
|
||||
const {
|
||||
formFields, values, errors, touched,
|
||||
formFields,
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
} = formData;
|
||||
|
||||
if (!Object.keys(formFields).length)
|
||||
@ -85,10 +89,14 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
setFormValues(formValues);
|
||||
}
|
||||
|
||||
const { dynamicFormFields, formValidations } = DynamicFormUtils.getFormData(fieldArray);
|
||||
const {
|
||||
dynamicFormFields,
|
||||
formValidations,
|
||||
} = DynamicFormUtils.getFormData(fieldArray);
|
||||
setInitialValues(initialValues);
|
||||
setFormFields(dynamicFormFields);
|
||||
setValidations(Yup.object().shape(formValidations));
|
||||
setValidations(Yup.object()
|
||||
.shape(formValidations));
|
||||
|
||||
forceUpdate();
|
||||
})();
|
||||
@ -107,7 +115,7 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
{
|
||||
window.location.href = `/${tableName}/${record.values.get(
|
||||
tableMetaData.primaryKeyField,
|
||||
)}`;
|
||||
)}?updateSuccess=true`;
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
@ -122,7 +130,7 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
{
|
||||
window.location.href = `/${tableName}/${record.values.get(
|
||||
tableMetaData.primaryKeyField,
|
||||
)}`;
|
||||
)}?createSuccess=true`;
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
@ -158,7 +166,10 @@ function EntityForm({ id }: Props): JSX.Element
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{({
|
||||
values, errors, touched, isSubmitting,
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
isSubmitting,
|
||||
}) => (
|
||||
<Form id={formId} autoComplete="off">
|
||||
<MDBox p={3} width="100%">
|
||||
|
@ -73,13 +73,7 @@ function Footer({ company, links }: Props): JSX.Element
|
||||
©
|
||||
{" "}
|
||||
{new Date().getFullYear()}
|
||||
, made with
|
||||
<MDBox fontSize={size.md} color="text" mb={-0.5} mx={0.25}>
|
||||
<Icon color="inherit" fontSize="inherit">
|
||||
favorite
|
||||
</Icon>
|
||||
</MDBox>
|
||||
by
|
||||
,
|
||||
<Link href={href} target="_blank">
|
||||
<MDTypography variant="button" fontWeight="medium">
|
||||
|
||||
@ -87,7 +81,6 @@ function Footer({ company, links }: Props): JSX.Element
|
||||
|
||||
</MDTypography>
|
||||
</Link>
|
||||
for a better web.
|
||||
</MDBox>
|
||||
<MDBox
|
||||
component="ul"
|
||||
@ -114,8 +107,8 @@ function Footer({ company, links }: Props): JSX.Element
|
||||
|
||||
// Declaring default props for Footer
|
||||
Footer.defaultProps = {
|
||||
company: { href: "https://www.kingsrook.com/", name: "Kingsrook" },
|
||||
links: [{ href: "https://www.kingsrook.com/", name: "Kingsrook" }],
|
||||
company: { href: "https://www.nutrifreshservices.com/", name: "Nutrifresh Services" },
|
||||
links: [],
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
|
@ -2,29 +2,25 @@
|
||||
=========================================================
|
||||
* Material Dashboard 2 PRO React TS - v1.0.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts
|
||||
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
|
||||
|
||||
Coded by www.creative-tim.com
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*/
|
||||
/* eslint-disable react/no-unstable-nested-components */
|
||||
|
||||
import React, { useEffect, useReducer, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
|
||||
// @mui material components
|
||||
import Card from "@mui/material/Card";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Link from "@mui/material/Link";
|
||||
import { makeStyles, Alert } from "@mui/material";
|
||||
import { Alert } from "@mui/material";
|
||||
import {
|
||||
DataGrid,
|
||||
GridCallbackDetails,
|
||||
@ -37,7 +33,11 @@ import {
|
||||
GridSelectionModel,
|
||||
GridSortItem,
|
||||
GridSortModel,
|
||||
GridToolbar, GridToolbarColumnsButton, GridToolbarContainer, GridToolbarDensitySelector, GridToolbarExport, GridToolbarFilterButton,
|
||||
GridToolbarColumnsButton,
|
||||
GridToolbarContainer,
|
||||
GridToolbarDensitySelector,
|
||||
GridToolbarExport,
|
||||
GridToolbarFilterButton,
|
||||
} from "@mui/x-data-grid";
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
@ -55,16 +55,18 @@ import { QFilterCriteria } from "@kingsrook/qqq-frontend-core/lib/model/query/QF
|
||||
import { QCriteriaOperator } from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator";
|
||||
import { QFieldType } from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
|
||||
import QClient from "qqq/utils/QClient";
|
||||
import MDAlert from "components/MDAlert";
|
||||
import Footer from "../../components/Footer";
|
||||
import QProcessUtils from "../../utils/QProcessUtils";
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
const COLUMN_VISIBILITY_LOCAL_STORAGE_KEY = "qqq.columnVisibility";
|
||||
const COLUMN_SORT_LOCAL_STORAGE_KEY = "qqq.columnSort";
|
||||
const COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT = "qqq.columnVisibility";
|
||||
const COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT = "qqq.columnSort";
|
||||
|
||||
// Declaring props types for DefaultCell
|
||||
interface Props {
|
||||
interface Props
|
||||
{
|
||||
table?: QTableMetaData;
|
||||
}
|
||||
|
||||
@ -73,6 +75,7 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const tableNameParam = useParams().tableName;
|
||||
const tableName = table === null ? tableNameParam : table.name;
|
||||
|
||||
const [buttonText, setButtonText] = useState("");
|
||||
const [tableState, setTableState] = useState("");
|
||||
const [filtersMenu, setFiltersMenu] = useState(null);
|
||||
const [actionsMenu, setActionsMenu] = useState(null);
|
||||
@ -89,7 +92,9 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const [sortModel, setSortModel] = useState([] as GridSortItem[]);
|
||||
const [filterModel, setFilterModel] = useState(null as GridFilterModel);
|
||||
const [alertContent, setAlertContent] = useState("");
|
||||
const [tableLabel, setTableLabel] = useState("");
|
||||
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
const openActionsMenu = (event: any) => setActionsMenu(event.currentTarget);
|
||||
@ -97,38 +102,41 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const openFiltersMenu = (event: any) => setFiltersMenu(event.currentTarget);
|
||||
const closeFiltersMenu = () => setFiltersMenu(null);
|
||||
|
||||
let columnVisibilityLocalStorageKey = "";
|
||||
let columnSortLocalStorageKey = "";
|
||||
|
||||
const translateCriteriaOperator = (operator: string) =>
|
||||
{
|
||||
switch (operator)
|
||||
{
|
||||
case "contains":
|
||||
return QCriteriaOperator.CONTAINS;
|
||||
case "starts with":
|
||||
return QCriteriaOperator.STARTS_WITH;
|
||||
case "ends with":
|
||||
case "startsWith":
|
||||
return QCriteriaOperator.STARTS_WITH;
|
||||
case "endsWith":
|
||||
return QCriteriaOperator.ENDS_WITH;
|
||||
case "is":
|
||||
case "equals":
|
||||
case "=":
|
||||
return QCriteriaOperator.EQUALS;
|
||||
case "is not":
|
||||
case "isNot":
|
||||
case "!=":
|
||||
return QCriteriaOperator.NOT_EQUALS;
|
||||
case "is after":
|
||||
case "after":
|
||||
case ">":
|
||||
return QCriteriaOperator.GREATER_THAN;
|
||||
case "is on or after":
|
||||
case "onOrAfter":
|
||||
case ">=":
|
||||
return QCriteriaOperator.GREATER_THAN_OR_EQUALS;
|
||||
case "is before":
|
||||
case "before":
|
||||
case "<":
|
||||
return QCriteriaOperator.LESS_THAN;
|
||||
case "is on or before":
|
||||
case "onOrBefore":
|
||||
case "<=":
|
||||
return QCriteriaOperator.LESS_THAN_OR_EQUALS;
|
||||
case "is empty":
|
||||
case "isEmpty":
|
||||
return QCriteriaOperator.IS_BLANK;
|
||||
case "is not empty":
|
||||
case "isNotEmpty":
|
||||
return QCriteriaOperator.IS_NOT_BLANK;
|
||||
// case "is any of":
|
||||
// TODO: handle this case
|
||||
@ -140,19 +148,24 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const buildQFilter = () =>
|
||||
{
|
||||
const qFilter = new QQueryFilter();
|
||||
sortModel.forEach((gridSortItem) =>
|
||||
if (sortModel)
|
||||
{
|
||||
qFilter.addOrderBy(new QFilterOrderBy(gridSortItem.field, gridSortItem.sort === "asc"));
|
||||
});
|
||||
sortModel.forEach((gridSortItem) =>
|
||||
{
|
||||
qFilter.addOrderBy(new QFilterOrderBy(gridSortItem.field, gridSortItem.sort === "asc"));
|
||||
});
|
||||
}
|
||||
if (filterModel)
|
||||
{
|
||||
filterModel.items.forEach((item) =>
|
||||
{
|
||||
qFilter.addCriteria(
|
||||
new QFilterCriteria(item.columnField, translateCriteriaOperator(item.operatorValue), [
|
||||
item.value,
|
||||
]),
|
||||
);
|
||||
const operator = translateCriteriaOperator(item.operatorValue);
|
||||
let criteria = new QFilterCriteria(item.columnField, operator, [item.value]);
|
||||
if (operator === QCriteriaOperator.IS_BLANK || operator === QCriteriaOperator.IS_NOT_BLANK)
|
||||
{
|
||||
criteria = new QFilterCriteria(item.columnField, translateCriteriaOperator(item.operatorValue), null);
|
||||
}
|
||||
qFilter.addCriteria(criteria);
|
||||
});
|
||||
}
|
||||
|
||||
@ -168,10 +181,17 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const tableMetaData = await QClient.loadTableMetaData(tableName);
|
||||
const count = await QClient.count(tableName, qFilter);
|
||||
setTotalRecords(count);
|
||||
setButtonText(`new ${tableMetaData.label}`);
|
||||
columnSortLocalStorageKey = `${COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT}.${tableMetaData.name}`;
|
||||
columnVisibilityLocalStorageKey = `${COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT}.${tableMetaData.name}`;
|
||||
setTableLabel(tableMetaData.label);
|
||||
|
||||
if (sortModel.length === 0)
|
||||
{
|
||||
sortModel.push({ field: tableMetaData.primaryKeyField, sort: "desc" });
|
||||
sortModel.push({
|
||||
field: tableMetaData.primaryKeyField,
|
||||
sort: "desc",
|
||||
});
|
||||
setSortModel(sortModel);
|
||||
}
|
||||
|
||||
@ -182,18 +202,19 @@ function EntityList({ table }: Props): JSX.Element
|
||||
qFilter,
|
||||
rowsPerPage,
|
||||
pageNumber * rowsPerPage,
|
||||
).catch((error) =>
|
||||
{
|
||||
if (error.message)
|
||||
)
|
||||
.catch((error) =>
|
||||
{
|
||||
setAlertContent(error.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAlertContent(error.response.data.error);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
if (error.message)
|
||||
{
|
||||
setAlertContent(error.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAlertContent(error.response.data.error);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
|
||||
const rows = [] as any[];
|
||||
results.forEach((record) =>
|
||||
@ -244,11 +265,11 @@ function EntityList({ table }: Props): JSX.Element
|
||||
}
|
||||
});
|
||||
|
||||
const columnVisibilityModel = localStorage.getItem(COLUMN_VISIBILITY_LOCAL_STORAGE_KEY);
|
||||
const columnVisibilityModel = localStorage.getItem(columnVisibilityLocalStorageKey);
|
||||
if (columnVisibilityModel)
|
||||
{
|
||||
setColumnVisibilityModel(
|
||||
JSON.parse(localStorage.getItem(COLUMN_VISIBILITY_LOCAL_STORAGE_KEY)),
|
||||
JSON.parse(localStorage.getItem(columnVisibilityLocalStorageKey)),
|
||||
);
|
||||
}
|
||||
setColumns(columns);
|
||||
@ -301,7 +322,7 @@ function EntityList({ table }: Props): JSX.Element
|
||||
{
|
||||
setColumnVisibilityModel(columnVisibilityModel);
|
||||
localStorage.setItem(
|
||||
COLUMN_VISIBILITY_LOCAL_STORAGE_KEY,
|
||||
columnVisibilityLocalStorageKey,
|
||||
JSON.stringify(columnVisibilityModel),
|
||||
);
|
||||
};
|
||||
@ -309,7 +330,7 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const handleSortChange = (gridSort: GridSortModel) =>
|
||||
{
|
||||
setSortModel(gridSort);
|
||||
localStorage.setItem(COLUMN_SORT_LOCAL_STORAGE_KEY, JSON.stringify(gridSort));
|
||||
localStorage.setItem(columnSortLocalStorageKey, JSON.stringify(gridSort));
|
||||
};
|
||||
|
||||
if (tableName !== tableState)
|
||||
@ -317,6 +338,10 @@ function EntityList({ table }: Props): JSX.Element
|
||||
(async () =>
|
||||
{
|
||||
setTableState(tableName);
|
||||
setSortModel([] as GridSortItem[]);
|
||||
setColumnVisibilityModel([] as GridColumnVisibilityModel[]);
|
||||
setFilterModel(null);
|
||||
setFiltersMenu(null);
|
||||
const metaData = await QClient.loadMetaData();
|
||||
|
||||
setTableProcesses(QProcessUtils.getProcessesForTable(metaData, tableName));
|
||||
@ -341,7 +366,11 @@ function EntityList({ table }: Props): JSX.Element
|
||||
The
|
||||
<strong>{` ${selectedIds.length.toLocaleString()} `}</strong>
|
||||
records on this page are selected.
|
||||
<button type="button" onClick={() => setSelectFullFilterState("filter")} className="MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButtonBase-root css-knwngq-MuiButtonBase-root-MuiButton-root">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelectFullFilterState("filter")}
|
||||
className="MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButtonBase-root css-knwngq-MuiButtonBase-root-MuiButton-root"
|
||||
>
|
||||
Select all
|
||||
{` ${totalRecords.toLocaleString()} `}
|
||||
records matching this query
|
||||
@ -355,7 +384,11 @@ function EntityList({ table }: Props): JSX.Element
|
||||
All
|
||||
<strong>{` ${totalRecords.toLocaleString()} `}</strong>
|
||||
records matching this query are selected.
|
||||
<button type="button" onClick={() => setSelectFullFilterState("checked")} className="MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButtonBase-root css-knwngq-MuiButtonBase-root-MuiButton-root">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelectFullFilterState("checked")}
|
||||
className="MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButtonBase-root css-knwngq-MuiButtonBase-root-MuiButton-root"
|
||||
>
|
||||
Select the
|
||||
{` ${selectedIds.length.toLocaleString()} `}
|
||||
records on this page
|
||||
@ -386,8 +419,14 @@ function EntityList({ table }: Props): JSX.Element
|
||||
const renderActionsMenu = (
|
||||
<Menu
|
||||
anchorEl={actionsMenu}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "left",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
open={Boolean(actionsMenu)}
|
||||
onClose={closeActionsMenu}
|
||||
keepMounted
|
||||
@ -402,6 +441,7 @@ function EntityList({ table }: Props): JSX.Element
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
console.log("UPDATING");
|
||||
updateTable();
|
||||
}, [pageNumber, rowsPerPage, tableState, sortModel, filterModel]);
|
||||
|
||||
@ -416,14 +456,25 @@ function EntityList({ table }: Props): JSX.Element
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
{
|
||||
(tableLabel && searchParams.get("deleteSuccess")) ? (
|
||||
<MDAlert color="success" dismissible>
|
||||
{`${tableLabel} successfully deleted`}
|
||||
</MDAlert>
|
||||
) : ("")
|
||||
}
|
||||
<MDBox display="flex" justifyContent="space-between" alignItems="flex-start" mb={2}>
|
||||
<Link href={`/${tableName}/create`}>
|
||||
<MDButton variant="gradient" color="info">
|
||||
new
|
||||
{" "}
|
||||
{tableName}
|
||||
</MDButton>
|
||||
</Link>
|
||||
{buttonText ? (
|
||||
<Link href={`/${tableName}/create`}>
|
||||
<MDButton variant="gradient" color="info">
|
||||
{
|
||||
buttonText
|
||||
}
|
||||
</MDButton>
|
||||
</Link>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<MDBox display="flex">
|
||||
{tableProcesses.length > 0 && (
|
||||
|
@ -2,19 +2,16 @@
|
||||
=========================================================
|
||||
* Material Dashboard 2 PRO React TS - v1.0.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts
|
||||
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
|
||||
|
||||
Coded by www.creative-tim.com
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*/
|
||||
|
||||
// react components
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
import React, { useReducer, useState } from "react";
|
||||
|
||||
// @material-ui core components
|
||||
@ -38,13 +35,15 @@ import MDTypography from "components/MDTypography";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import MDAlert from "components/MDAlert";
|
||||
import MDButton from "../../../../../components/MDButton";
|
||||
import QProcessUtils from "../../../../utils/QProcessUtils";
|
||||
|
||||
const qController = new QController("");
|
||||
|
||||
// Declaring props types for ViewForm
|
||||
interface Props {
|
||||
interface Props
|
||||
{
|
||||
id: string;
|
||||
}
|
||||
|
||||
@ -58,6 +57,7 @@ function ViewContents({ id }: Props): JSX.Element
|
||||
const [tableMetaData, setTableMetaData] = useState(null);
|
||||
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
||||
const [actionsMenu, setActionsMenu] = useState(null);
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
const openActionsMenu = (event: any) => setActionsMenu(event.currentTarget);
|
||||
@ -130,10 +130,11 @@ function ViewContents({ id }: Props): JSX.Element
|
||||
event.preventDefault();
|
||||
(async () =>
|
||||
{
|
||||
await qController.delete(tableName, id).then(() =>
|
||||
{
|
||||
window.location.href = `/${tableName}`;
|
||||
});
|
||||
await qController.delete(tableName, id)
|
||||
.then(() =>
|
||||
{
|
||||
window.location.href = `/${tableName}?deleteSuccess=true`;
|
||||
});
|
||||
})();
|
||||
};
|
||||
|
||||
@ -142,8 +143,14 @@ function ViewContents({ id }: Props): JSX.Element
|
||||
const renderActionsMenu = (
|
||||
<Menu
|
||||
anchorEl={actionsMenu}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "left",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
open={Boolean(actionsMenu)}
|
||||
onClose={closeActionsMenu}
|
||||
keepMounted
|
||||
@ -157,76 +164,90 @@ function ViewContents({ id }: Props): JSX.Element
|
||||
);
|
||||
|
||||
return (
|
||||
<Card id="basic-info" sx={{ overflow: "visible" }}>
|
||||
<MDBox p={3}>
|
||||
<MDBox display="flex" justifyContent="space-between">
|
||||
<MDTypography variant="h5">
|
||||
Viewing
|
||||
{" "}
|
||||
|
||||
<MDBox pb={3}>
|
||||
{
|
||||
(searchParams.get("createSuccess") || searchParams.get("updateSuccess")) ? (
|
||||
<MDAlert color="success" dismissible>
|
||||
{tableMetaData?.label}
|
||||
{" "}
|
||||
(
|
||||
{id}
|
||||
)
|
||||
</MDTypography>
|
||||
{tableProcesses.length > 0 && (
|
||||
<MDButton
|
||||
variant={actionsMenu ? "contained" : "outlined"}
|
||||
color="dark"
|
||||
onClick={openActionsMenu}
|
||||
>
|
||||
actions
|
||||
<Icon>keyboard_arrow_down</Icon>
|
||||
</MDButton>
|
||||
)}
|
||||
{renderActionsMenu}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
<MDBox p={3}>{nameValues}</MDBox>
|
||||
<MDBox component="form" pb={3} px={3}>
|
||||
<Grid key="tres" container spacing={3}>
|
||||
<MDBox ml="auto" mr={3}>
|
||||
<MDButton
|
||||
variant="gradient"
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={handleClickConfirmOpen}
|
||||
>
|
||||
delete
|
||||
successfully
|
||||
{" "}
|
||||
{searchParams.get("createSuccess") ? "created" : "updated"}
|
||||
|
||||
</MDAlert>
|
||||
) : ("")
|
||||
}
|
||||
<Card id="basic-info" sx={{ overflow: "visible" }}>
|
||||
<MDBox p={3}>
|
||||
<MDBox display="flex" justifyContent="space-between">
|
||||
<MDTypography variant="h5">
|
||||
Viewing
|
||||
{" "}
|
||||
{tableMetaData?.label}
|
||||
</MDButton>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={handleClickConfirmClose}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">Confirm Deletion</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to delete this record?
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleClickConfirmClose}>No</Button>
|
||||
<Button onClick={handleDelete} autoFocus>
|
||||
Yes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
{" "}
|
||||
(
|
||||
{id}
|
||||
)
|
||||
</MDTypography>
|
||||
{tableProcesses.length > 0 && (
|
||||
<MDButton
|
||||
variant={actionsMenu ? "contained" : "outlined"}
|
||||
color="dark"
|
||||
onClick={openActionsMenu}
|
||||
>
|
||||
actions
|
||||
<Icon>keyboard_arrow_down</Icon>
|
||||
</MDButton>
|
||||
)}
|
||||
{renderActionsMenu}
|
||||
</MDBox>
|
||||
<MDBox>
|
||||
<MDButton variant="gradient" color="dark" size="small">
|
||||
<Link href={editPath}>
|
||||
edit
|
||||
</MDBox>
|
||||
<MDBox p={3}>{nameValues}</MDBox>
|
||||
<MDBox component="form" pb={3} px={3}>
|
||||
<Grid key="tres" container spacing={3}>
|
||||
<MDBox ml="auto" mr={3}>
|
||||
<MDButton
|
||||
variant="gradient"
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={handleClickConfirmOpen}
|
||||
>
|
||||
delete
|
||||
{" "}
|
||||
{tableMetaData?.label}
|
||||
</Link>
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
</Card>
|
||||
</MDButton>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={handleClickConfirmClose}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">Confirm Deletion</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to delete this record?
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleClickConfirmClose}>No</Button>
|
||||
<Button onClick={handleDelete} autoFocus>
|
||||
Yes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</MDBox>
|
||||
<MDBox>
|
||||
<MDButton variant="gradient" color="dark" size="small">
|
||||
<Link href={editPath}>
|
||||
{`edit ${tableMetaData?.label}`}
|
||||
</Link>
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
</Card>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user