diff --git a/.prettierrc.json b/.prettierrc.json
index 40fa8e5..f553e50 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,7 +1,6 @@
{
"printWidth": 100,
"trailingComma": "es5",
- "tabWidth": 2,
"semi": true,
"singleQuote": false,
"endOfLine": "auto"
diff --git a/package-lock.json b/package-lock.json
index 95485ca..dbf124e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,6 +20,7 @@
"@mui/icons-material": "5.4.1",
"@mui/material": "5.4.1",
"@mui/styled-engine": "5.4.1",
+ "@mui/x-data-grid": "5.13.0",
"@react-jvectormap/core": "1.0.1",
"@react-jvectormap/world": "1.0.0",
"@testing-library/jest-dom": "5.16.2",
@@ -3291,6 +3292,31 @@
"react": "^17.0.0 || ^18.0.0"
}
},
+ "node_modules/@mui/x-data-grid": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-5.13.0.tgz",
+ "integrity": "sha512-x310qsOJFIT0JuqnDusM6DC4hlX6eeL9biEveb/y+hdeLa+VHSwrclS0M7e9UUwmh1MPza6VT4ceEWJjbySf3A==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.2",
+ "@mui/utils": "^5.4.1",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "reselect": "^4.1.6"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.4.1",
+ "@mui/system": "^5.4.1",
+ "react": "^17.0.2 || ^18.0.0",
+ "react-dom": "^17.0.2 || ^18.0.0"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -5934,9 +5960,9 @@
}
},
"node_modules/clsx": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
- "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"engines": {
"node": ">=6"
}
@@ -14466,6 +14492,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
+ "node_modules/reselect": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
+ "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
+ },
"node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -19213,6 +19244,18 @@
"react-is": "^17.0.2"
}
},
+ "@mui/x-data-grid": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-5.13.0.tgz",
+ "integrity": "sha512-x310qsOJFIT0JuqnDusM6DC4hlX6eeL9biEveb/y+hdeLa+VHSwrclS0M7e9UUwmh1MPza6VT4ceEWJjbySf3A==",
+ "requires": {
+ "@babel/runtime": "^7.17.2",
+ "@mui/utils": "^5.4.1",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "reselect": "^4.1.6"
+ }
+ },
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -21178,9 +21221,9 @@
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
},
"clsx": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
- "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
},
"co": {
"version": "4.6.0",
@@ -27233,6 +27276,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
+ "reselect": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
+ "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
+ },
"resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
diff --git a/package.json b/package.json
index b8327ad..f0d6140 100644
--- a/package.json
+++ b/package.json
@@ -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.1",
+ "@kingsrook/qqq-frontend-core": "file:.yalc/@kingsrook/qqq-frontend-core",
"@mui/icons-material": "5.4.1",
"@mui/material": "5.4.1",
"@mui/styled-engine": "5.4.1",
diff --git a/src/App.tsx b/src/App.tsx
index d8c5d34..f37268e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -13,7 +13,14 @@ 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, useEffect, JSXElementConstructor, Key, ReactElement } from "react";
+import React, {
+ useState,
+ useEffect,
+ JSXElementConstructor,
+ Key,
+ ReactElement,
+ useReducer,
+} from "react";
// react-router components
import { Routes, Route, Navigate, useLocation } from "react-router-dom";
diff --git a/src/examples/LayoutContainers/DashboardLayout/index.tsx b/src/examples/LayoutContainers/DashboardLayout/index.tsx
index 3f92daf..fb53257 100644
--- a/src/examples/LayoutContainers/DashboardLayout/index.tsx
+++ b/src/examples/LayoutContainers/DashboardLayout/index.tsx
@@ -1,19 +1,19 @@
/**
-=========================================================
-* Material Dashboard 2 PRO React TS - v1.0.0
-=========================================================
+ =========================================================
+ * 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)
+ * 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
+ 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.
+ */
-import { useEffect, ReactNode } from "react";
+import { useEffect, ReactNode, useReducer, useState } from "react";
// react-router-dom components
import { useLocation } from "react-router-dom";
diff --git a/src/layouts/dashboards/analytics/index.tsx b/src/layouts/dashboards/analytics/index.tsx
index 8cba5b1..31e8fbd 100644
--- a/src/layouts/dashboards/analytics/index.tsx
+++ b/src/layouts/dashboards/analytics/index.tsx
@@ -42,9 +42,11 @@ import reportsLineChartData from "layouts/dashboards/analytics/data/reportsLineC
import booking1 from "assets/images/products/product-1-min.jpg";
import booking2 from "assets/images/products/product-2-min.jpg";
import booking3 from "assets/images/products/product-3-min.jpg";
+import { useReducer } from "react";
function Analytics(): JSX.Element {
const { sales, tasks } = reportsLineChartData;
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
// Action buttons for the BookingCard
const actionButtons = (
diff --git a/src/qqq/components/EntityForm/index.tsx b/src/qqq/components/EntityForm/index.tsx
index dee41fc..383a4ae 100644
--- a/src/qqq/components/EntityForm/index.tsx
+++ b/src/qqq/components/EntityForm/index.tsx
@@ -15,8 +15,10 @@ import { QFieldMetaData } from "@kingsrook/qqq-frontend-core/lib/model/metaData/
// @material-ui core components
import Card from "@mui/material/Card";
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";
@@ -33,6 +35,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);
const [formValues, setFormValues] = useState({} as { [key: string]: string });
@@ -85,17 +88,27 @@ function EntityForm({ id }: Props): JSX.Element {
actions.setSubmitting(true);
await (async () => {
if (id !== null) {
- await qController.update(tableName, id, values).then((record) => {
- window.location.href = `/${tableName}/${record.values.get(
- tableMetaData.primaryKeyField
- )}`;
- });
+ await qController
+ .update(tableName, id, values)
+ .then((record) => {
+ window.location.href = `/${tableName}/${record.values.get(
+ tableMetaData.primaryKeyField
+ )}`;
+ })
+ .catch((error) => {
+ setAlertContent(error.response.data.error);
+ });
} else {
- await qController.create(tableName, values).then((record) => {
- window.location.href = `/${tableName}/${record.values.get(
- tableMetaData.primaryKeyField
- )}`;
- });
+ await qController
+ .create(tableName, values)
+ .then((record) => {
+ window.location.href = `/${tableName}/${record.values.get(
+ tableMetaData.primaryKeyField
+ )}`;
+ })
+ .catch((error) => {
+ setAlertContent(error.response.data.error);
+ });
}
})();
};
@@ -106,43 +119,56 @@ function EntityForm({ id }: Props): JSX.Element {
id != null ? `edit-${tableMetaData?.label}-form` : `create-${tableMetaData?.label}-form`;
return (
-