mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 13:20:43 +00:00
QQQ-32 udpating styles on query; record list & view sections; record labels; apps in nav; updated breadcrumb; updated navigation
This commit is contained in:
@ -1,16 +1,22 @@
|
||||
/**
|
||||
=========================================================
|
||||
* 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.
|
||||
/*
|
||||
* 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 {useState, useEffect, ReactNode} from "react";
|
||||
@ -22,7 +28,6 @@ import breakpoints from "assets/theme/base/breakpoints";
|
||||
import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
|
||||
import Navbar from "qqq/components/Navbar";
|
||||
import Footer from "qqq/components/Footer";
|
||||
import DashboardNavbar from "examples/Navbars/DashboardNavbar";
|
||||
import MDBox from "../../../components/MDBox";
|
||||
|
||||
// Declaring props types for BaseLayout
|
||||
@ -60,7 +65,7 @@ function BaseLayout({stickyNavbar, children}: Props): JSX.Element
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Navbar />
|
||||
<MDBox mt={stickyNavbar ? 3 : 10}>{children}</MDBox>
|
||||
<MDBox mt={stickyNavbar ? 3 : 6}>{children}</MDBox>
|
||||
<Footer />
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* 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 {useAuth0} from "@auth0/auth0-react";
|
||||
import React from "react";
|
||||
import {Button} from "@mui/material";
|
||||
|
@ -1,57 +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)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import MDAvatar from "components/MDAvatar";
|
||||
|
||||
// Declaring props types for CustomerCell
|
||||
interface Props {
|
||||
image?: string;
|
||||
name: string;
|
||||
color?:
|
||||
| "transparent"
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "error"
|
||||
| "light"
|
||||
| "dark";
|
||||
}
|
||||
|
||||
function CustomerCell({image, name, color}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox display="flex" alignItems="center">
|
||||
<MDBox mr={1}>
|
||||
<MDAvatar bgColor={color} src={image} alt={name} size="xs" />
|
||||
</MDBox>
|
||||
<MDTypography variant="caption" fontWeight="medium" color="text" sx={{lineHeight: 0}}>
|
||||
{name}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for CustomerCell
|
||||
CustomerCell.defaultProps = {
|
||||
image: "",
|
||||
color: "dark",
|
||||
};
|
||||
|
||||
export default CustomerCell;
|
@ -1,45 +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)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDTypography from "components/MDTypography";
|
||||
|
||||
// Declaring props types for DefaultCell
|
||||
interface Props {
|
||||
value: string;
|
||||
suffix?: string | boolean;
|
||||
}
|
||||
|
||||
function DefaultCell({value, suffix}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDTypography variant="caption" fontWeight="medium" color="text">
|
||||
{value}
|
||||
{suffix && (
|
||||
<MDTypography variant="caption" fontWeight="medium" color="secondary">
|
||||
|
||||
{suffix}
|
||||
</MDTypography>
|
||||
)}
|
||||
</MDTypography>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for DefaultCell
|
||||
DefaultCell.defaultProps = {
|
||||
suffix: "",
|
||||
};
|
||||
|
||||
export default DefaultCell;
|
@ -1,54 +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)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// @mui material components
|
||||
import Checkbox from "@mui/material/Checkbox";
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import Link from "@mui/material/Link";
|
||||
|
||||
// Declaring props types for IdCell
|
||||
interface Props {
|
||||
id: string;
|
||||
checked?: boolean;
|
||||
}
|
||||
|
||||
function IdCell({id, checked}: Props): JSX.Element
|
||||
{
|
||||
const pathParts = window.location.pathname.split("/");
|
||||
const tableName = pathParts[1];
|
||||
const href = `/${tableName}/${id}`;
|
||||
const link = <Link href={href}>{id}</Link>;
|
||||
|
||||
return (
|
||||
<MDBox display="flex" alignItems="center">
|
||||
<Checkbox defaultChecked={checked} />
|
||||
<MDBox ml={1}>
|
||||
<MDTypography variant="caption" fontWeight="medium" color="text">
|
||||
{link}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for IdCell
|
||||
IdCell.defaultProps = {
|
||||
checked: false,
|
||||
};
|
||||
|
||||
export default IdCell;
|
@ -1,57 +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)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// @mui material components
|
||||
import Icon from "@mui/material/Icon";
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import MDButton from "components/MDButton";
|
||||
|
||||
// Declaring props types for StatusCell
|
||||
interface Props {
|
||||
icon: string;
|
||||
color:
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "error"
|
||||
| "dark"
|
||||
| "light"
|
||||
| "white"
|
||||
| "default";
|
||||
status: string;
|
||||
}
|
||||
|
||||
function StatusCell({icon, color, status}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox display="flex" alignItems="center">
|
||||
<MDBox mr={1}>
|
||||
<MDButton variant="outlined" color={color} size="small" iconOnly circular>
|
||||
<Icon sx={{fontWeight: "bold"}}>{icon}</Icon>
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
<MDTypography variant="caption" fontWeight="medium" color="text" sx={{lineHeight: 0}}>
|
||||
{status}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
export default StatusCell;
|
@ -1,193 +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)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
const selectData = {
|
||||
gender: ["Male", "Female"],
|
||||
birthDate: [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
],
|
||||
days: [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
"17",
|
||||
"18",
|
||||
"19",
|
||||
"20",
|
||||
"21",
|
||||
"22",
|
||||
"23",
|
||||
"24",
|
||||
"25",
|
||||
"26",
|
||||
"27",
|
||||
"28",
|
||||
"29",
|
||||
"30",
|
||||
],
|
||||
years: [
|
||||
"1900",
|
||||
"1901",
|
||||
"1902",
|
||||
"1903",
|
||||
"1904",
|
||||
"1905",
|
||||
"1906",
|
||||
"1907",
|
||||
"1908",
|
||||
"1909",
|
||||
"1910",
|
||||
"1911",
|
||||
"1912",
|
||||
"1913",
|
||||
"1914",
|
||||
"1915",
|
||||
"1915",
|
||||
"1915",
|
||||
"1916",
|
||||
"1917",
|
||||
"1918",
|
||||
"1919",
|
||||
"1920",
|
||||
"1921",
|
||||
"1922",
|
||||
"1923",
|
||||
"1924",
|
||||
"1925",
|
||||
"1926",
|
||||
"1927",
|
||||
"1928",
|
||||
"1929",
|
||||
"1930",
|
||||
"1931",
|
||||
"1932",
|
||||
"1933",
|
||||
"1934",
|
||||
"1935",
|
||||
"1936",
|
||||
"1937",
|
||||
"1938",
|
||||
"1939",
|
||||
"1940",
|
||||
"1941",
|
||||
"1942",
|
||||
"1943",
|
||||
"1944",
|
||||
"1945",
|
||||
"1946",
|
||||
"1947",
|
||||
"1948",
|
||||
"1949",
|
||||
"1950",
|
||||
"1951",
|
||||
"1952",
|
||||
"1953",
|
||||
"1954",
|
||||
"1955",
|
||||
"1956",
|
||||
"1957",
|
||||
"1958",
|
||||
"1959",
|
||||
"1960",
|
||||
"1961",
|
||||
"1962",
|
||||
"1963",
|
||||
"1964",
|
||||
"1965",
|
||||
"1966",
|
||||
"1967",
|
||||
"1968",
|
||||
"1969",
|
||||
"1970",
|
||||
"1971",
|
||||
"1972",
|
||||
"1973",
|
||||
"1974",
|
||||
"1975",
|
||||
"1976",
|
||||
"1977",
|
||||
"1978",
|
||||
"1979",
|
||||
"1980",
|
||||
"1981",
|
||||
"1982",
|
||||
"1983",
|
||||
"1984",
|
||||
"1985",
|
||||
"1986",
|
||||
"1987",
|
||||
"1988",
|
||||
"1989",
|
||||
"1990",
|
||||
"1991",
|
||||
"1992",
|
||||
"1993",
|
||||
"1994",
|
||||
"1995",
|
||||
"1996",
|
||||
"1997",
|
||||
"1998",
|
||||
"1999",
|
||||
"2000",
|
||||
"2001",
|
||||
"2002",
|
||||
"2003",
|
||||
"2004",
|
||||
"2005",
|
||||
"2006",
|
||||
"2007",
|
||||
"2008",
|
||||
"2009",
|
||||
"2010",
|
||||
"2011",
|
||||
"2012",
|
||||
"2013",
|
||||
"2014",
|
||||
"2015",
|
||||
"2016",
|
||||
"2017",
|
||||
"2018",
|
||||
"2019",
|
||||
"2020",
|
||||
"2021",
|
||||
],
|
||||
skills: ["react", "vue", "angular", "svelte", "javascript"],
|
||||
};
|
||||
|
||||
export default selectData;
|
@ -1,13 +1,14 @@
|
||||
// react components
|
||||
import {useParams, useSearchParams} from "react-router-dom";
|
||||
import {useParams, useNavigate, useLocation} from "react-router-dom";
|
||||
import React, {useReducer, useState} from "react";
|
||||
|
||||
// misc components
|
||||
import * as Yup from "yup";
|
||||
import {Form, Formik} from "formik";
|
||||
import {
|
||||
Form, Formik, useFormik, useFormikContext,
|
||||
} from "formik";
|
||||
|
||||
// qqq components
|
||||
import {QController} from "@kingsrook/qqq-frontend-core/lib/controllers/QController";
|
||||
import DynamicFormUtils from "qqq/components/QDynamicForm/utils/DynamicFormUtils";
|
||||
import QDynamicForm from "qqq/components/QDynamicForm";
|
||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||
@ -20,45 +21,61 @@ import {Alert} from "@mui/material";
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import MDButton from "../../../components/MDButton";
|
||||
import QClient from "qqq/utils/QClient";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import {QCancelButton, QSaveButton} from "qqq/components/QButtons";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import QRecordSidebar from "qqq/components/QRecordSidebar";
|
||||
import QTableUtils from "qqq/utils/QTableUtils";
|
||||
|
||||
// Declaring props types for EntityForm
|
||||
interface Props
|
||||
{
|
||||
id?: string;
|
||||
id?: string;
|
||||
table?: QTableMetaData;
|
||||
}
|
||||
|
||||
function EntityForm({id}: Props): JSX.Element
|
||||
function EntityForm({table, id}: Props): JSX.Element
|
||||
{
|
||||
const qController = QClient.getInstance();
|
||||
const {tableName} = useParams();
|
||||
const tableNameParam = useParams().tableName;
|
||||
const tableName = table === null ? tableNameParam : table.name;
|
||||
|
||||
const [validations, setValidations] = useState({});
|
||||
const [initialValues, setInitialValues] = useState({} as { [key: string]: string });
|
||||
const [formFields, setFormFields] = useState({});
|
||||
const [formFields, setFormFields] = useState(null as Map<string, any>);
|
||||
const [t1sectionName, setT1SectionName] = useState(null as string);
|
||||
|
||||
const [alertContent, setAlertContent] = useState("");
|
||||
|
||||
const [asyncLoadInited, setAsyncLoadInited] = useState(false);
|
||||
const [formValues, setFormValues] = useState({} as { [key: string]: string });
|
||||
const [tableMetaData, setTableMetaData] = useState(null);
|
||||
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
|
||||
const [record, setRecord] = useState(null as QRecord);
|
||||
const [tableSections, setTableSections] = useState(null as any);
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
function getDynamicStepContent(formData: any): JSX.Element
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
function getFormSection(values: any, touched: any, formFields: any, errors: any): JSX.Element
|
||||
{
|
||||
const {
|
||||
formFields,
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
} = formData;
|
||||
const formData: any = {};
|
||||
formData.values = values;
|
||||
formData.touched = touched;
|
||||
formData.errors = errors;
|
||||
formData.formFields = {};
|
||||
console.log(formFields);
|
||||
for (let i = 0; i < formFields.length; i++)
|
||||
{
|
||||
formData.formFields[formFields[i].name] = formFields[i];
|
||||
}
|
||||
|
||||
if (!Object.keys(formFields).length)
|
||||
{
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return <QDynamicForm formData={formData} primaryKeyId={tableMetaData.primaryKeyField} />;
|
||||
}
|
||||
|
||||
@ -70,20 +87,27 @@ function EntityForm({id}: Props): JSX.Element
|
||||
const tableMetaData = await qController.loadTableMetaData(tableName);
|
||||
setTableMetaData(tableMetaData);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// define the sections, e.g., for the left-bar //
|
||||
/////////////////////////////////////////////////
|
||||
const tableSections = QTableUtils.getSectionsForRecordSidebar(tableMetaData);
|
||||
setTableSections(tableSections);
|
||||
|
||||
const fieldArray = [] as QFieldMetaData[];
|
||||
const sortedKeys = [...tableMetaData.fields.keys()].sort();
|
||||
sortedKeys.forEach((key) =>
|
||||
{
|
||||
const fieldMetaData = tableMetaData.fields.get(key);
|
||||
if (fieldMetaData.isEditable)
|
||||
{
|
||||
fieldArray.push(fieldMetaData);
|
||||
}
|
||||
fieldArray.push(fieldMetaData);
|
||||
});
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// if doing an edit, fetch the record and pre-populate the form values from it //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
if (id !== null)
|
||||
{
|
||||
const record = await qController.get(tableName, id);
|
||||
setRecord(record);
|
||||
|
||||
tableMetaData.fields.forEach((fieldMetaData, key) =>
|
||||
{
|
||||
@ -92,20 +116,79 @@ function EntityForm({id}: Props): JSX.Element
|
||||
|
||||
setFormValues(formValues);
|
||||
}
|
||||
setInitialValues(initialValues);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// get formField and formValidation objects for Formik //
|
||||
/////////////////////////////////////////////////////////
|
||||
const {
|
||||
dynamicFormFields,
|
||||
formValidations,
|
||||
} = DynamicFormUtils.getFormData(fieldArray);
|
||||
setInitialValues(initialValues);
|
||||
setFormFields(dynamicFormFields);
|
||||
setValidations(Yup.object()
|
||||
.shape(formValidations));
|
||||
|
||||
/////////////////////////////////////
|
||||
// group the formFields by section //
|
||||
/////////////////////////////////////
|
||||
const dynamicFormFieldsBySection = new Map<string, any>();
|
||||
let t1sectionName;
|
||||
for (let i = 0; i < tableSections.length; i++)
|
||||
{
|
||||
const section = tableSections[i];
|
||||
const sectionDynamicFormFields: any[] = [];
|
||||
|
||||
for (let j = 0; j < section.fieldNames.length; j++)
|
||||
{
|
||||
const fieldName = section.fieldNames[j];
|
||||
const field = tableMetaData.fields.get(fieldName);
|
||||
if (id !== null || field.isEditable)
|
||||
{
|
||||
sectionDynamicFormFields.push(dynamicFormFields[fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
if (sectionDynamicFormFields.length === 0)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// in case there are no active fields in this section, remove it from the tableSections array //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
tableSections.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynamicFormFieldsBySection.set(section.name, sectionDynamicFormFields);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// capture the tier1 section's name //
|
||||
//////////////////////////////////////
|
||||
if (section.tier === "T1")
|
||||
{
|
||||
t1sectionName = section.name;
|
||||
}
|
||||
}
|
||||
setT1SectionName(t1sectionName);
|
||||
setFormFields(dynamicFormFieldsBySection);
|
||||
setValidations(Yup.object().shape(formValidations));
|
||||
|
||||
forceUpdate();
|
||||
})();
|
||||
}
|
||||
|
||||
const handleCancelClicked = () =>
|
||||
{
|
||||
if (id !== null)
|
||||
{
|
||||
const path = `${location.pathname.replace(/\/edit$/, "")}`;
|
||||
navigate(path, {replace: true});
|
||||
}
|
||||
else
|
||||
{
|
||||
const path = `${location.pathname.replace(/\/create$/, "")}`;
|
||||
navigate(path, {replace: true});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async (values: any, actions: any) =>
|
||||
{
|
||||
actions.setSubmitting(true);
|
||||
@ -117,9 +200,8 @@ function EntityForm({id}: Props): JSX.Element
|
||||
.update(tableName, id, values)
|
||||
.then((record) =>
|
||||
{
|
||||
window.location.href = `/${tableName}/${record.values.get(
|
||||
tableMetaData.primaryKeyField,
|
||||
)}?updateSuccess=true`;
|
||||
const path = `${location.pathname.replace(/\/edit$/, "")}?updateSuccess=true`;
|
||||
navigate(path);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
@ -132,9 +214,8 @@ function EntityForm({id}: Props): JSX.Element
|
||||
.create(tableName, values)
|
||||
.then((record) =>
|
||||
{
|
||||
window.location.href = `/${tableName}/${record.values.get(
|
||||
tableMetaData.primaryKeyField,
|
||||
)}?createSuccess=true`;
|
||||
const path = `${location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField))}?createSuccess=true`;
|
||||
navigate(path);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
@ -144,8 +225,20 @@ function EntityForm({id}: Props): JSX.Element
|
||||
})();
|
||||
};
|
||||
|
||||
const formTitle = id != null ? `Edit ${tableMetaData?.label} (${id})` : `Create New ${tableMetaData?.label}`;
|
||||
const formId = id != null ? `edit-${tableMetaData?.label}-form` : `create-${tableMetaData?.label}-form`;
|
||||
let formTitle = "";
|
||||
if (tableMetaData)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
formTitle = `Create new ${tableMetaData?.label}`;
|
||||
}
|
||||
else if (record != null)
|
||||
{
|
||||
formTitle = `Edit ${tableMetaData?.label}: ${record?.recordLabel}`;
|
||||
}
|
||||
}
|
||||
|
||||
const formId = id != null ? `edit-${tableMetaData?.name}-form` : `create-${tableMetaData?.name}-form`;
|
||||
|
||||
return (
|
||||
<MDBox mb={3}>
|
||||
@ -155,62 +248,91 @@ function EntityForm({id}: Props): JSX.Element
|
||||
<MDBox mb={3}>
|
||||
<Alert severity="error">{alertContent}</Alert>
|
||||
</MDBox>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<Card id="edit-form-container" sx={{overflow: "visible"}}>
|
||||
<MDBox p={3}>
|
||||
<MDTypography variant="h5">{formTitle}</MDTypography>
|
||||
</MDBox>
|
||||
<MDBox pb={3} px={3}>
|
||||
<Grid key="fields-grid" container spacing={3}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validations}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
isSubmitting,
|
||||
}) => (
|
||||
<Form id={formId} autoComplete="off">
|
||||
<MDBox p={3} width="100%">
|
||||
{/***************************************************************************
|
||||
** step content - e.g., the appropriate form or other screen for the step **
|
||||
***************************************************************************/}
|
||||
{getDynamicStepContent({
|
||||
values,
|
||||
touched,
|
||||
formFields,
|
||||
errors,
|
||||
})}
|
||||
<Grid key="buttonGrid" container spacing={3}>
|
||||
<MDBox mt={5} ml="auto">
|
||||
<MDButton type="submit" variant="gradient" color="dark" size="small">
|
||||
save
|
||||
{" "}
|
||||
{tableMetaData?.label}
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</Grid>
|
||||
) : ("")}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} lg={3}>
|
||||
<QRecordSidebar tableSections={tableSections} />
|
||||
</Grid>
|
||||
<Grid item xs={12} lg={9}>
|
||||
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validations}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
isSubmitting,
|
||||
}) => (
|
||||
<Form id={formId} autoComplete="off">
|
||||
|
||||
<MDBox pb={3} pt={0}>
|
||||
<Card id={`${t1sectionName}`} sx={{overflow: "visible"}}>
|
||||
<MDBox display="flex" p={3} pb={1}>
|
||||
<MDBox mr={1.5}>
|
||||
<Avatar sx={{bgcolor: "rgb(26, 115, 232)"}}>
|
||||
<Icon>
|
||||
{tableMetaData?.iconName}
|
||||
</Icon>
|
||||
</Avatar>
|
||||
</MDBox>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
</Card>
|
||||
<MDBox display="flex" alignItems="center">
|
||||
<MDTypography variant="h5">{formTitle}</MDTypography>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
{
|
||||
t1sectionName && formFields ? (
|
||||
<MDBox pb={3} px={3}>
|
||||
<MDBox p={3} width="100%">
|
||||
{getFormSection(values, touched, formFields.get(t1sectionName), errors)}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
) : null
|
||||
}
|
||||
</Card>
|
||||
</MDBox>
|
||||
{tableSections && formFields ? tableSections.map((section: any) => (section.name !== t1sectionName
|
||||
? (
|
||||
<MDBox key={`edit-card-${section.name}`} pb={3}>
|
||||
<Card id={section.name} sx={{overflow: "visible"}}>
|
||||
<MDTypography variant="h5" p={3} pb={1}>
|
||||
{section.label}
|
||||
</MDTypography>
|
||||
<MDBox pb={3} px={3}>
|
||||
<MDBox p={3} width="100%">
|
||||
{
|
||||
getFormSection(values, touched, formFields.get(section.name), errors)
|
||||
}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
</Card>
|
||||
</MDBox>
|
||||
) : null)) : null}
|
||||
|
||||
<MDBox component="div" p={3}>
|
||||
<Grid container justifyContent="flex-end" spacing={3}>
|
||||
<QCancelButton onClickHandler={handleCancelClicked} />
|
||||
<QSaveButton />
|
||||
</Grid>
|
||||
</MDBox>
|
||||
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for DefaultCell
|
||||
EntityForm.defaultProps = {
|
||||
id: null,
|
||||
table: null,
|
||||
};
|
||||
|
||||
export default EntityForm;
|
||||
|
@ -1,17 +1,23 @@
|
||||
/**
|
||||
=========================================================
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// @mui material components
|
||||
import Link from "@mui/material/Link";
|
||||
@ -60,6 +66,9 @@ function Footer({company, links}: Props): JSX.Element
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
px={1.5}
|
||||
style={{
|
||||
position: "fixed", bottom: "0px", zIndex: -1, marginBottom: "10px",
|
||||
}}
|
||||
>
|
||||
<MDBox
|
||||
display="flex"
|
||||
|
@ -1,7 +1,28 @@
|
||||
/*
|
||||
* 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 {useState, useEffect} from "react";
|
||||
|
||||
// react-router components
|
||||
import {useLocation, Link} from "react-router-dom";
|
||||
import {useLocation} from "react-router-dom";
|
||||
|
||||
// @material-ui core components
|
||||
import AppBar from "@mui/material/AppBar";
|
||||
@ -16,7 +37,6 @@ import MDInput from "components/MDInput";
|
||||
import MDBadge from "components/MDBadge";
|
||||
|
||||
// Material Dashboard 2 PRO React TS examples components
|
||||
import Breadcrumbs from "examples/Breadcrumbs";
|
||||
import NotificationItem from "examples/Items/NotificationItem";
|
||||
|
||||
// Custom styles for Navbar
|
||||
@ -38,6 +58,7 @@ import {
|
||||
} from "context";
|
||||
|
||||
// qqq
|
||||
import QBreadcrumbs from "qqq/components/QBreadcrumbs";
|
||||
|
||||
// Declaring prop types for Navbar
|
||||
interface Props
|
||||
@ -106,9 +127,11 @@ function Navbar({absolute, light, isMini}: Props): JSX.Element
|
||||
onClose={handleCloseMenu}
|
||||
sx={{mt: 2}}
|
||||
>
|
||||
<NotificationItem icon={<Icon>email</Icon>} title="Check new messages" />
|
||||
<NotificationItem icon={<Icon>email</Icon>} title="0 messages available" />
|
||||
{/*
|
||||
<NotificationItem icon={<Icon>podcasts</Icon>} title="Manage Podcast sessions" />
|
||||
<NotificationItem icon={<Icon>shopping_cart</Icon>} title="Payment successfully completed" />
|
||||
*/}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@ -145,7 +168,7 @@ function Navbar({absolute, light, isMini}: Props): JSX.Element
|
||||
>
|
||||
<Toolbar sx={navbarContainer}>
|
||||
<MDBox color="inherit" mb={{xs: 1, md: 0}} sx={(theme) => navbarRow(theme, {isMini})}>
|
||||
<Breadcrumbs icon="home" title={breadcrumbTitle} route={route} light={light} />
|
||||
<QBreadcrumbs icon="home" title={breadcrumbTitle} route={route} light={light} />
|
||||
<IconButton sx={navbarDesktopMenu} onClick={handleMiniSidenav} size="small" disableRipple>
|
||||
<Icon fontSize="medium" sx={iconsStyle}>
|
||||
{miniSidenav ? "menu_open" : "menu"}
|
||||
@ -184,7 +207,7 @@ function Navbar({absolute, light, isMini}: Props): JSX.Element
|
||||
sx={navbarIconButton}
|
||||
onClick={handleOpenMenu}
|
||||
>
|
||||
<MDBadge badgeContent={9} color="error" size="xs" circular>
|
||||
<MDBadge badgeContent={0} color="error" size="xs" circular>
|
||||
<Icon sx={iconsStyle}>notifications</Icon>
|
||||
</MDBadge>
|
||||
</IconButton>
|
||||
|
@ -1,16 +1,22 @@
|
||||
/**
|
||||
=========================================================
|
||||
* 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.
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// @mui material components
|
||||
|
105
src/qqq/components/ProcessLinkCard/index.tsx
Normal file
105
src/qqq/components/ProcessLinkCard/index.tsx
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 {ReactNode} from "react";
|
||||
|
||||
// @mui material components
|
||||
import Card from "@mui/material/Card";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Icon from "@mui/material/Icon";
|
||||
|
||||
// Material Dashboard 2 PRO React TS components
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/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;
|
||||
}
|
||||
|
||||
function ProcessLinkCard({
|
||||
color, title, percentage, icon,
|
||||
}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<Card>
|
||||
<MDBox display="flex" justifyContent="space-between" pt={1} px={2}>
|
||||
<MDBox
|
||||
variant="gradient"
|
||||
bgColor={color}
|
||||
color={color === "light" ? "dark" : "white"}
|
||||
coloredShadow={color}
|
||||
borderRadius="xl"
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
width="4rem"
|
||||
height="4rem"
|
||||
mt={-3}
|
||||
>
|
||||
<Icon fontSize="medium" color="inherit">
|
||||
{icon}
|
||||
</Icon>
|
||||
</MDBox>
|
||||
<MDBox textAlign="right" lineHeight={1.25}>
|
||||
<MDTypography variant="button" fontWeight="bold" color="text">
|
||||
{title}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
<Divider />
|
||||
<MDBox pb={2} px={2}>
|
||||
<MDTypography component="p" variant="button" color="text" display="flex">
|
||||
<MDTypography
|
||||
component="span"
|
||||
variant="button"
|
||||
fontWeight="bold"
|
||||
color={percentage.color}
|
||||
>
|
||||
{percentage.amount}
|
||||
</MDTypography>
|
||||
Click here to run the process called
|
||||
{" "}
|
||||
{title}
|
||||
.
|
||||
{percentage.label}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
ProcessLinkCard.defaultProps = {
|
||||
color: "info",
|
||||
percentage: {
|
||||
color: "success",
|
||||
text: "",
|
||||
label: "",
|
||||
},
|
||||
};
|
||||
|
||||
export default ProcessLinkCard;
|
133
src/qqq/components/QBreadcrumbs/index.tsx
Normal file
133
src/qqq/components/QBreadcrumbs/index.tsx
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 {ReactNode} from "react";
|
||||
|
||||
import {Link} from "react-router-dom";
|
||||
import {Breadcrumbs as MuiBreadcrumbs} from "@mui/material";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
|
||||
interface Props {
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
route: string | string[];
|
||||
light?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const ucFirst = (input: string): string =>
|
||||
{
|
||||
if (!input)
|
||||
{
|
||||
return (input);
|
||||
}
|
||||
return (input.substring(0, 1).toUpperCase() + input.substring(1));
|
||||
};
|
||||
|
||||
const routeToLabel = (route: string): string =>
|
||||
{
|
||||
const label = ucFirst(route.replace(".", " ").replace("-", " ").replace("_", " ").replace(/([A-Z])/g, " $1"));
|
||||
return (label);
|
||||
};
|
||||
|
||||
function QBreadcrumbs({
|
||||
icon, title, route, light,
|
||||
}: Props): JSX.Element
|
||||
{
|
||||
const routes: string[] | any = route.slice(0, -1);
|
||||
|
||||
let pageTitle = "Nutrifresh One";
|
||||
const fullRoutes: string[] = [];
|
||||
let accumulatedPath = "";
|
||||
for (let i = 0; i < routes.length; i++)
|
||||
{
|
||||
accumulatedPath = `${accumulatedPath}/${routes[i]}`;
|
||||
fullRoutes.push(accumulatedPath);
|
||||
pageTitle = `${routeToLabel(routes[i])} | ${pageTitle}`;
|
||||
}
|
||||
|
||||
document.title = `${ucFirst(title)} | ${pageTitle}`;
|
||||
|
||||
return (
|
||||
<MDBox mr={{xs: 0, xl: 8}}>
|
||||
<MuiBreadcrumbs
|
||||
sx={{
|
||||
"& .MuiBreadcrumbs-separator": {
|
||||
color: ({palette: {white, grey}}) => (light ? white.main : grey[600]),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link to="/">
|
||||
<MDTypography
|
||||
component="span"
|
||||
variant="body2"
|
||||
color={light ? "white" : "dark"}
|
||||
opacity={light ? 0.8 : 0.5}
|
||||
sx={{lineHeight: 0}}
|
||||
>
|
||||
<Icon>{icon}</Icon>
|
||||
</MDTypography>
|
||||
</Link>
|
||||
{fullRoutes.map((fullRoute: string) => (
|
||||
<Link to={fullRoute} key={fullRoute}>
|
||||
<MDTypography
|
||||
component="span"
|
||||
variant="button"
|
||||
fontWeight="regular"
|
||||
textTransform="capitalize"
|
||||
color={light ? "white" : "dark"}
|
||||
opacity={light ? 0.8 : 0.5}
|
||||
sx={{lineHeight: 0}}
|
||||
>
|
||||
{routeToLabel(fullRoute.replace(/.*\//, ""))}
|
||||
</MDTypography>
|
||||
</Link>
|
||||
))}
|
||||
<MDTypography
|
||||
variant="button"
|
||||
fontWeight="regular"
|
||||
textTransform="capitalize"
|
||||
color={light ? "white" : "dark"}
|
||||
sx={{lineHeight: 0}}
|
||||
>
|
||||
{routeToLabel(title)}
|
||||
</MDTypography>
|
||||
</MuiBreadcrumbs>
|
||||
<MDTypography
|
||||
fontWeight="bold"
|
||||
textTransform="capitalize"
|
||||
variant="h6"
|
||||
color={light ? "white" : "dark"}
|
||||
noWrap
|
||||
>
|
||||
{routeToLabel(title)}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
QBreadcrumbs.defaultProps = {
|
||||
light: false,
|
||||
};
|
||||
|
||||
export default QBreadcrumbs;
|
126
src/qqq/components/QButtons/index.tsx
Normal file
126
src/qqq/components/QButtons/index.tsx
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 MDBox from "components/MDBox";
|
||||
import {Link} from "react-router-dom";
|
||||
import MDButton from "components/MDButton";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import React from "react";
|
||||
|
||||
// eslint-disable import/prefer-default-export
|
||||
|
||||
const standardWidth = "150px";
|
||||
|
||||
export function QCreateNewButton(): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox ml={3} mr={2} width={standardWidth}>
|
||||
<Link to="create">
|
||||
<MDButton variant="gradient" color="info" fullWidth startIcon={<Icon>add</Icon>}>
|
||||
Create New
|
||||
</MDButton>
|
||||
</Link>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
export function QSaveButton(): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox ml={3} width={standardWidth}>
|
||||
<MDButton type="submit" variant="gradient" color="info" size="small" fullWidth startIcon={<Icon>save</Icon>}>
|
||||
Save
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
interface QDeleteButtonProps
|
||||
{
|
||||
onClickHandler: any
|
||||
}
|
||||
|
||||
export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox ml={3} mr={3}>
|
||||
<MDBox width={standardWidth}>
|
||||
<MDButton variant="gradient" color="primary" size="small" onClick={onClickHandler} fullWidth startIcon={<Icon>delete</Icon>}>
|
||||
Delete
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
export function QEditButton(): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox>
|
||||
<Link to="edit">
|
||||
<MDBox width={standardWidth}>
|
||||
<MDButton variant="gradient" color="dark" size="small" fullWidth startIcon={<Icon>edit</Icon>}>
|
||||
Edit
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</Link>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
interface QActionsMenuButtonProps
|
||||
{
|
||||
isOpen: boolean;
|
||||
onClickHandler: any;
|
||||
}
|
||||
|
||||
export function QActionsMenuButton({isOpen, onClickHandler}: QActionsMenuButtonProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox width={standardWidth}>
|
||||
<MDButton
|
||||
variant={isOpen ? "contained" : "outlined"}
|
||||
color="dark"
|
||||
onClick={onClickHandler}
|
||||
fullWidth
|
||||
>
|
||||
actions
|
||||
<Icon>keyboard_arrow_down</Icon>
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
||||
|
||||
interface QCancelButtonProps
|
||||
{
|
||||
onClickHandler: any;
|
||||
}
|
||||
|
||||
export function QCancelButton({onClickHandler}: QCancelButtonProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<MDBox ml="auto" width={standardWidth}>
|
||||
<MDButton type="button" variant="outlined" color="dark" size="small" fullWidth startIcon={<Icon>cancel</Icon>} onClick={onClickHandler}>
|
||||
Cancel
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
);
|
||||
}
|
@ -77,10 +77,6 @@ function QDynamicForm(props: Props): JSX.Element
|
||||
&& Object.keys(formFields).map((fieldName: any) =>
|
||||
{
|
||||
const field = formFields[fieldName];
|
||||
if (primaryKeyId && fieldName === primaryKeyId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (values[fieldName] === undefined)
|
||||
{
|
||||
values[fieldName] = "";
|
||||
@ -109,17 +105,18 @@ function QDynamicForm(props: Props): JSX.Element
|
||||
|
||||
// todo? inputProps={{ autoComplete: "" }}
|
||||
// todo? placeholder={password.placeholder}
|
||||
// todo? success={!errors[fieldName] && touched[fieldName]}
|
||||
return (
|
||||
<Grid item xs={12} sm={6} key={fieldName}>
|
||||
<QDynamicFormField
|
||||
type={field.type}
|
||||
label={field.label}
|
||||
isEditable={field.isEditable}
|
||||
name={fieldName}
|
||||
value={values[fieldName]}
|
||||
error={errors[fieldName] && touched[fieldName]}
|
||||
bulkEditMode={bulkEditMode}
|
||||
bulkEditSwitchChangeHandler={bulkEditSwitchChanged}
|
||||
success={!errors[fieldName] && touched[fieldName]}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
|
@ -83,6 +83,7 @@ class DynamicFormUtils
|
||||
name: field.name,
|
||||
label: label,
|
||||
isRequired: field.isRequired,
|
||||
isEditable: field.isEditable,
|
||||
type: fieldType,
|
||||
// todo invalidMsg: "Zipcode is not valid (e.g. 70000).",
|
||||
});
|
||||
|
@ -36,24 +36,33 @@ interface Props
|
||||
{
|
||||
label: string;
|
||||
name: string;
|
||||
type: string;
|
||||
isEditable?: boolean;
|
||||
[key: string]: any;
|
||||
bulkEditMode?: boolean;
|
||||
bulkEditSwitchChangeHandler?: any
|
||||
}
|
||||
|
||||
function QDynamicFormField({
|
||||
label, name, bulkEditMode, bulkEditSwitchChangeHandler, ...rest
|
||||
label, name, bulkEditMode, bulkEditSwitchChangeHandler, type, isEditable, ...rest
|
||||
}: Props): JSX.Element
|
||||
{
|
||||
const [switchChecked, setSwitchChecked] = useState(false);
|
||||
const [isDisabled, setIsDisabled] = useState(bulkEditMode);
|
||||
const [isDisabled, setIsDisabled] = useState(!isEditable || bulkEditMode);
|
||||
|
||||
const inputLabelProps = {};
|
||||
if (type.toLowerCase().match("(date|time)"))
|
||||
{
|
||||
// @ts-ignore
|
||||
inputLabelProps.shrink = true;
|
||||
}
|
||||
|
||||
const field = () => (
|
||||
<>
|
||||
<Field {...rest} name={name} as={MDInput} variant="standard" label={label} fullWidth disabled={isDisabled} />
|
||||
<Field {...rest} name={name} type={type} as={MDInput} variant="standard" label={label} InputLabelProps={inputLabelProps} fullWidth disabled={isDisabled} />
|
||||
<MDBox mt={0.75}>
|
||||
<MDTypography component="div" variant="caption" color="error" fontWeight="regular">
|
||||
{!isDisabled && <ErrorMessage name={name} />}
|
||||
{!isDisabled && <div className="fieldErrorMessage"><ErrorMessage name={name} /></div>}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</>
|
||||
@ -100,6 +109,7 @@ function QDynamicFormField({
|
||||
|
||||
QDynamicFormField.defaultProps = {
|
||||
bulkEditMode: false,
|
||||
isEditable: true,
|
||||
bulkEditSwitchChangeHandler: () =>
|
||||
{},
|
||||
};
|
||||
|
84
src/qqq/components/QRecordSidebar/index.tsx
Normal file
84
src/qqq/components/QRecordSidebar/index.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 React, {ReactNode} from "react";
|
||||
|
||||
import {Link} from "react-router-dom";
|
||||
import {Breadcrumbs as MuiBreadcrumbs} from "@mui/material";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import MDBox from "components/MDBox";
|
||||
import MDTypography from "components/MDTypography";
|
||||
import Card from "@mui/material/Card";
|
||||
import {Theme} from "@mui/material/styles";
|
||||
|
||||
interface Props {
|
||||
tableSections: any;
|
||||
light?: boolean;
|
||||
}
|
||||
|
||||
function QRecordSidebar({tableSections, light}: Props): JSX.Element
|
||||
{
|
||||
return (
|
||||
<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(({icon, label, name}: any, key: number) => (
|
||||
<MDBox key={`section-${name}`} component="li" pt={key === 0 ? 0 : 1}>
|
||||
<MDTypography
|
||||
component="a"
|
||||
href={`#${name}`}
|
||||
variant="button"
|
||||
fontWeight="regular"
|
||||
sx={({
|
||||
borders: {borderRadius}, functions: {pxToRem}, palette: {light}, transitions,
|
||||
}: Theme) => ({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
borderRadius: borderRadius.md,
|
||||
padding: `${pxToRem(10)} ${pxToRem(16)}`,
|
||||
transition: transitions.create("background-color", {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
"&:hover": {
|
||||
backgroundColor: light.main,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<MDBox mr={1.5} lineHeight={1} color="black">
|
||||
<Icon fontSize="small">{icon}</Icon>
|
||||
</MDBox>
|
||||
{label}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
)) : null
|
||||
}
|
||||
</MDBox>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
QRecordSidebar.defaultProps = {
|
||||
light: false,
|
||||
};
|
||||
|
||||
export default QRecordSidebar;
|
Reference in New Issue
Block a user