mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
Feedback from code reviews
This commit is contained in:
@ -60,6 +60,7 @@
|
|||||||
"max-len": "off",
|
"max-len": "off",
|
||||||
"no-console": "off",
|
"no-console": "off",
|
||||||
"no-constant-condition": "off",
|
"no-constant-condition": "off",
|
||||||
|
"no-continue": "off",
|
||||||
"no-shadow": "off",
|
"no-shadow": "off",
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"no-plusplus": "off",
|
"no-plusplus": "off",
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"@fullcalendar/interaction": "5.10.0",
|
"@fullcalendar/interaction": "5.10.0",
|
||||||
"@fullcalendar/react": "5.10.0",
|
"@fullcalendar/react": "5.10.0",
|
||||||
"@fullcalendar/timegrid": "5.10.0",
|
"@fullcalendar/timegrid": "5.10.0",
|
||||||
"@kingsrook/qqq-frontend-core": "1.0.8",
|
"@kingsrook/qqq-frontend-core": "1.0.9",
|
||||||
"@mui/icons-material": "5.4.1",
|
"@mui/icons-material": "5.4.1",
|
||||||
"@mui/material": "5.4.1",
|
"@mui/material": "5.4.1",
|
||||||
"@mui/styled-engine": "5.4.1",
|
"@mui/styled-engine": "5.4.1",
|
||||||
|
111
src/App.tsx
111
src/App.tsx
@ -35,7 +35,6 @@ import {setMiniSidenav, setOpenConfigurator, useMaterialUIController} from "cont
|
|||||||
import nfLogo from "assets/images/nutrifresh_one_icon_white.png";
|
import nfLogo from "assets/images/nutrifresh_one_icon_white.png";
|
||||||
import {Md5} from "ts-md5/dist/md5";
|
import {Md5} from "ts-md5/dist/md5";
|
||||||
import {useCookies} from "react-cookie";
|
import {useCookies} from "react-cookie";
|
||||||
import {QAppMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppMetaData";
|
|
||||||
import EntityCreate from "./qqq/pages/entity-create";
|
import EntityCreate from "./qqq/pages/entity-create";
|
||||||
import EntityList from "./qqq/pages/entity-list";
|
import EntityList from "./qqq/pages/entity-list";
|
||||||
import EntityView from "./qqq/pages/entity-view";
|
import EntityView from "./qqq/pages/entity-view";
|
||||||
@ -51,6 +50,7 @@ import QClient from "./qqq/utils/QClient";
|
|||||||
import {QAppNodeType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppNodeType";
|
import {QAppNodeType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppNodeType";
|
||||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||||
import QProcessUtils from "qqq/utils/QProcessUtils";
|
import QProcessUtils from "qqq/utils/QProcessUtils";
|
||||||
|
import {QAppTreeNode} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppTreeNode";
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// define the parts of the nav that are static - before the qqq tables etc get dynamic added //
|
// define the parts of the nav that are static - before the qqq tables etc get dynamic added //
|
||||||
@ -94,6 +94,7 @@ export default function App()
|
|||||||
} = useAuth0();
|
} = useAuth0();
|
||||||
const [loadingToken, setLoadingToken] = useState(false);
|
const [loadingToken, setLoadingToken] = useState(false);
|
||||||
const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false);
|
const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false);
|
||||||
|
const [profileRoutes, setProfileRoutes] = useState({});
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -137,8 +138,6 @@ export default function App()
|
|||||||
const [sideNavRoutes, setSideNavRoutes] = useState(getStaticRoutes());
|
const [sideNavRoutes, setSideNavRoutes] = useState(getStaticRoutes());
|
||||||
const [appRoutes, setAppRoutes] = useState(null as any);
|
const [appRoutes, setAppRoutes] = useState(null as any);
|
||||||
|
|
||||||
const dynamicAppChildElement = <AppHome />;
|
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
// load qqq meta data to make more routes //
|
// load qqq meta data to make more routes //
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
@ -152,7 +151,7 @@ export default function App()
|
|||||||
|
|
||||||
(async () =>
|
(async () =>
|
||||||
{
|
{
|
||||||
function addAppToSideNavList(app: QAppMetaData, appList: any[], parentPath: string, depth: number)
|
function addAppToSideNavList(app: QAppTreeNode, appList: any[], parentPath: string, depth: number)
|
||||||
{
|
{
|
||||||
const path = `${parentPath}/${app.name}`;
|
const path = `${parentPath}/${app.name}`;
|
||||||
if (app.type !== QAppNodeType.APP)
|
if (app.type !== QAppNodeType.APP)
|
||||||
@ -160,62 +159,65 @@ export default function App()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.type === QAppNodeType.APP && depth <= 2)
|
if (depth > 2)
|
||||||
{
|
{
|
||||||
const childList: any[] = [];
|
console.warn("App depth is greater than 2 - not including app in side nav...");
|
||||||
app.children.forEach((child: QAppMetaData) =>
|
return;
|
||||||
{
|
}
|
||||||
addAppToSideNavList(child, childList, path, depth + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (childList.length === 0)
|
const childList: any[] = [];
|
||||||
{
|
app.children.forEach((child: QAppTreeNode) =>
|
||||||
if (depth === 0)
|
{
|
||||||
{
|
addAppToSideNavList(child, childList, path, depth + 1);
|
||||||
/////////////////////////////////////////////////////
|
});
|
||||||
// at level 0, the entry must always be a collapse //
|
|
||||||
/////////////////////////////////////////////////////
|
if (childList.length === 0)
|
||||||
appList.push({
|
{
|
||||||
type: "collapse",
|
if (depth === 0)
|
||||||
name: app.label,
|
|
||||||
key: app.name,
|
|
||||||
route: path,
|
|
||||||
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
|
||||||
noCollapse: true,
|
|
||||||
component: <AppHome />,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appList.push({
|
|
||||||
name: app.label,
|
|
||||||
key: app.name,
|
|
||||||
route: path,
|
|
||||||
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
|
||||||
component: <AppHome />,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
// at level 0, the entry must always be a collapse //
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
appList.push({
|
appList.push({
|
||||||
type: "collapse",
|
type: "collapse",
|
||||||
name: app.label,
|
name: app.label,
|
||||||
key: app.name,
|
key: app.name,
|
||||||
dropdown: true,
|
route: path,
|
||||||
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
||||||
collapse: childList,
|
noCollapse: true,
|
||||||
|
component: <AppHome />,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appList.push({
|
||||||
|
name: app.label,
|
||||||
|
key: app.name,
|
||||||
|
route: path,
|
||||||
|
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
||||||
|
component: <AppHome />,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appList.push({
|
||||||
|
type: "collapse",
|
||||||
|
name: app.label,
|
||||||
|
key: app.name,
|
||||||
|
dropdown: true,
|
||||||
|
icon: <Icon fontSize="medium">{app.iconName}</Icon>,
|
||||||
|
collapse: childList,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAppToAppRoutesList(metaData: QInstance, app: QAppMetaData, routeList: any[], parentPath: string, depth: number)
|
function addAppToAppRoutesList(metaData: QInstance, app: QAppTreeNode, routeList: any[], parentPath: string, depth: number)
|
||||||
{
|
{
|
||||||
const path = `${parentPath}/${app.name}`;
|
const path = `${parentPath}/${app.name}`;
|
||||||
if (app.type === QAppNodeType.APP)
|
if (app.type === QAppNodeType.APP)
|
||||||
{
|
{
|
||||||
app.children.forEach((child: QAppMetaData) =>
|
app.children.forEach((child: QAppTreeNode) =>
|
||||||
{
|
{
|
||||||
addAppToAppRoutesList(metaData, child, routeList, path, depth + 1);
|
addAppToAppRoutesList(metaData, child, routeList, path, depth + 1);
|
||||||
});
|
});
|
||||||
@ -261,16 +263,6 @@ export default function App()
|
|||||||
const processesForTable = QProcessUtils.getProcessesForTable(metaData, table.name, true);
|
const processesForTable = QProcessUtils.getProcessesForTable(metaData, table.name, true);
|
||||||
processesForTable.forEach((process) =>
|
processesForTable.forEach((process) =>
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// special provision for the standard bulk processes - strip the table name from the process name //
|
|
||||||
// todo - this var isn't used - is this needed?
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
let processName = process.name;
|
|
||||||
if (processName.startsWith(`${process.tableName}.`))
|
|
||||||
{
|
|
||||||
processName = processName.replace(`${process.tableName}.`, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
routeList.push({
|
routeList.push({
|
||||||
name: process.label,
|
name: process.label,
|
||||||
key: process.name,
|
key: process.name,
|
||||||
@ -295,11 +287,11 @@ export default function App()
|
|||||||
{
|
{
|
||||||
const metaData = await QClient.getInstance().loadMetaData();
|
const metaData = await QClient.getInstance().loadMetaData();
|
||||||
|
|
||||||
let profileRoute = {};
|
let profileRoutes = {};
|
||||||
const gravatarBase = "http://www.gravatar.com/avatar/";
|
const gravatarBase = "http://www.gravatar.com/avatar/";
|
||||||
const hash = Md5.hashStr(user.email);
|
const hash = Md5.hashStr(user.email);
|
||||||
const profilePicture = `${gravatarBase}${hash}`;
|
const profilePicture = `${gravatarBase}${hash}`;
|
||||||
profileRoute = {
|
profileRoutes = {
|
||||||
type: "collapse",
|
type: "collapse",
|
||||||
name: user.name,
|
name: user.name,
|
||||||
key: user.name,
|
key: user.name,
|
||||||
@ -319,6 +311,7 @@ export default function App()
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
setProfileRoutes(profileRoutes);
|
||||||
|
|
||||||
const sideNavAppList = [] as any[];
|
const sideNavAppList = [] as any[];
|
||||||
const appRoutesList = [] as any[];
|
const appRoutesList = [] as any[];
|
||||||
@ -331,7 +324,7 @@ export default function App()
|
|||||||
|
|
||||||
const newSideNavRoutes = getStaticRoutes();
|
const newSideNavRoutes = getStaticRoutes();
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
newSideNavRoutes.unshift(profileRoute);
|
newSideNavRoutes.unshift(profileRoutes);
|
||||||
for (let i = 0; i < sideNavAppList.length; i++)
|
for (let i = 0; i < sideNavAppList.length; i++)
|
||||||
{
|
{
|
||||||
newSideNavRoutes.push(sideNavAppList[i]);
|
newSideNavRoutes.push(sideNavAppList[i]);
|
||||||
@ -386,6 +379,9 @@ export default function App()
|
|||||||
document.scrollingElement.scrollTop = 0;
|
document.scrollingElement.scrollTop = 0;
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// convert an object that works for the Sidenav into one that works for the react-router //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const getRoutes = (allRoutes: any[]): any => allRoutes.map(
|
const getRoutes = (allRoutes: any[]): any => allRoutes.map(
|
||||||
(route: {
|
(route: {
|
||||||
collapse: any;
|
collapse: any;
|
||||||
@ -452,7 +448,8 @@ export default function App()
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path="*" element={<Navigate to="/dashboards/analytics" />} />
|
<Route path="*" element={<Navigate to="/dashboards/analytics" />} />
|
||||||
{appRoutes && getRoutes(appRoutes)}
|
{appRoutes && getRoutes(appRoutes)}
|
||||||
{sideNavRoutes && getRoutes(sideNavRoutes)}
|
{getRoutes(getStaticRoutes())}
|
||||||
|
{profileRoutes && getRoutes([profileRoutes])}
|
||||||
</Routes>
|
</Routes>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
|
@ -29,6 +29,8 @@ import Avatar from "@mui/material/Avatar";
|
|||||||
import Icon from "@mui/material/Icon";
|
import Icon from "@mui/material/Icon";
|
||||||
import QRecordSidebar from "qqq/components/QRecordSidebar";
|
import QRecordSidebar from "qqq/components/QRecordSidebar";
|
||||||
import QTableUtils from "qqq/utils/QTableUtils";
|
import QTableUtils from "qqq/utils/QTableUtils";
|
||||||
|
import colors from "assets/theme/base/colors";
|
||||||
|
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
@ -46,6 +48,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
const [initialValues, setInitialValues] = useState({} as { [key: string]: string });
|
const [initialValues, setInitialValues] = useState({} as { [key: string]: string });
|
||||||
const [formFields, setFormFields] = useState(null as Map<string, any>);
|
const [formFields, setFormFields] = useState(null as Map<string, any>);
|
||||||
const [t1sectionName, setT1SectionName] = useState(null as string);
|
const [t1sectionName, setT1SectionName] = useState(null as string);
|
||||||
|
const [nonT1Sections, setNonT1Sections] = useState([] as QSection[]);
|
||||||
|
|
||||||
const [alertContent, setAlertContent] = useState("");
|
const [alertContent, setAlertContent] = useState("");
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
const [formValues, setFormValues] = useState({} as { [key: string]: string });
|
const [formValues, setFormValues] = useState({} as { [key: string]: string });
|
||||||
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
|
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
|
||||||
const [record, setRecord] = useState(null as QRecord);
|
const [record, setRecord] = useState(null as QRecord);
|
||||||
const [tableSections, setTableSections] = useState(null as any);
|
const [tableSections, setTableSections] = useState(null as QSection[]);
|
||||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -76,7 +79,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
return <QDynamicForm formData={formData} primaryKeyId={tableMetaData.primaryKeyField} />;
|
return <QDynamicForm formData={formData} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asyncLoadInited)
|
if (!asyncLoadInited)
|
||||||
@ -131,6 +134,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
const dynamicFormFieldsBySection = new Map<string, any>();
|
const dynamicFormFieldsBySection = new Map<string, any>();
|
||||||
let t1sectionName;
|
let t1sectionName;
|
||||||
|
const nonT1Sections: QSection[] = [];
|
||||||
for (let i = 0; i < tableSections.length; i++)
|
for (let i = 0; i < tableSections.length; i++)
|
||||||
{
|
{
|
||||||
const section = tableSections[i];
|
const section = tableSections[i];
|
||||||
@ -140,6 +144,11 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
const fieldName = section.fieldNames[j];
|
const fieldName = section.fieldNames[j];
|
||||||
const field = tableMetaData.fields.get(fieldName);
|
const field = tableMetaData.fields.get(fieldName);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if id !== null - means we're on the edit screen -- show all fields on the edit screen. //
|
||||||
|
// || (or) we're on the insert screen in which case, only show editable fields. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if (id !== null || field.isEditable)
|
if (id !== null || field.isEditable)
|
||||||
{
|
{
|
||||||
sectionDynamicFormFields.push(dynamicFormFields[fieldName]);
|
sectionDynamicFormFields.push(dynamicFormFields[fieldName]);
|
||||||
@ -153,6 +162,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
tableSections.splice(i, 1);
|
tableSections.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -166,8 +176,13 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
t1sectionName = section.name;
|
t1sectionName = section.name;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nonT1Sections.push(section);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setT1SectionName(t1sectionName);
|
setT1SectionName(t1sectionName);
|
||||||
|
setNonT1Sections(nonT1Sections);
|
||||||
setFormFields(dynamicFormFieldsBySection);
|
setFormFields(dynamicFormFieldsBySection);
|
||||||
setValidations(Yup.object().shape(formValidations));
|
setValidations(Yup.object().shape(formValidations));
|
||||||
|
|
||||||
@ -177,6 +192,11 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
|
|
||||||
const handleCancelClicked = () =>
|
const handleCancelClicked = () =>
|
||||||
{
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// todo - we might have rather just done a navigate(-1) (to keep history clean) //
|
||||||
|
// but if the user used the anchors on the page, this doesn't effectively cancel... //
|
||||||
|
// what we have here pushed a new history entry (I think?), so could be better //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
if (id !== null)
|
if (id !== null)
|
||||||
{
|
{
|
||||||
const path = `${location.pathname.replace(/\/edit$/, "")}`;
|
const path = `${location.pathname.replace(/\/edit$/, "")}`;
|
||||||
@ -274,7 +294,7 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
<Card id={`${t1sectionName}`} sx={{overflow: "visible"}}>
|
<Card id={`${t1sectionName}`} sx={{overflow: "visible"}}>
|
||||||
<MDBox display="flex" p={3} pb={1}>
|
<MDBox display="flex" p={3} pb={1}>
|
||||||
<MDBox mr={1.5}>
|
<MDBox mr={1.5}>
|
||||||
<Avatar sx={{bgcolor: "rgb(26, 115, 232)"}}>
|
<Avatar sx={{bgcolor: colors.info.main}}>
|
||||||
<Icon>
|
<Icon>
|
||||||
{tableMetaData?.iconName}
|
{tableMetaData?.iconName}
|
||||||
</Icon>
|
</Icon>
|
||||||
@ -295,23 +315,22 @@ function EntityForm({table, id}: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
</Card>
|
</Card>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
{tableSections && formFields ? tableSections.map((section: any) => (section.name !== t1sectionName
|
{formFields && nonT1Sections.length ? nonT1Sections.map((section: QSection) => (
|
||||||
? (
|
<MDBox key={`edit-card-${section.name}`} pb={3}>
|
||||||
<MDBox key={`edit-card-${section.name}`} pb={3}>
|
<Card id={section.name} sx={{overflow: "visible"}}>
|
||||||
<Card id={section.name} sx={{overflow: "visible"}}>
|
<MDTypography variant="h5" p={3} pb={1}>
|
||||||
<MDTypography variant="h5" p={3} pb={1}>
|
{section.label}
|
||||||
{section.label}
|
</MDTypography>
|
||||||
</MDTypography>
|
<MDBox pb={3} px={3}>
|
||||||
<MDBox pb={3} px={3}>
|
<MDBox p={3} width="100%">
|
||||||
<MDBox p={3} width="100%">
|
{
|
||||||
{
|
getFormSection(values, touched, formFields.get(section.name), errors)
|
||||||
getFormSection(values, touched, formFields.get(section.name), errors)
|
}
|
||||||
}
|
|
||||||
</MDBox>
|
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Card>
|
</MDBox>
|
||||||
</MDBox>
|
</Card>
|
||||||
) : null)) : null}
|
</MDBox>
|
||||||
|
)) : null}
|
||||||
|
|
||||||
<MDBox component="div" p={3}>
|
<MDBox component="div" p={3}>
|
||||||
<Grid container justifyContent="flex-end" spacing={3}>
|
<Grid container justifyContent="flex-end" spacing={3}>
|
||||||
|
@ -58,7 +58,7 @@ import {
|
|||||||
} from "context";
|
} from "context";
|
||||||
|
|
||||||
// qqq
|
// qqq
|
||||||
import QBreadcrumbs from "qqq/components/QBreadcrumbs";
|
import QBreadcrumbs, {routeToLabel} from "qqq/components/QBreadcrumbs";
|
||||||
|
|
||||||
// Declaring prop types for Navbar
|
// Declaring prop types for Navbar
|
||||||
interface Props
|
interface Props
|
||||||
@ -156,7 +156,7 @@ function Navbar({absolute, light, isMini}: Props): JSX.Element
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const breadcrumbTitle = route[route.length - 1].replace(/([A-Z])/g, " $1").trim();
|
const breadcrumbTitle = routeToLabel(route[route.length - 1]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBar
|
<AppBar
|
||||||
|
@ -44,9 +44,14 @@ const ucFirst = (input: string): string =>
|
|||||||
return (input.substring(0, 1).toUpperCase() + input.substring(1));
|
return (input.substring(0, 1).toUpperCase() + input.substring(1));
|
||||||
};
|
};
|
||||||
|
|
||||||
const routeToLabel = (route: string): string =>
|
export const routeToLabel = (route: string): string =>
|
||||||
{
|
{
|
||||||
const label = ucFirst(route.replace(".", " ").replace("-", " ").replace("_", " ").replace(/([A-Z])/g, " $1"));
|
const label = ucFirst(route
|
||||||
|
.replace(".", " ")
|
||||||
|
.replace("-", " ")
|
||||||
|
.replace("_", " ")
|
||||||
|
.replace(/([a-z])([A-Z]+)/g, "$1 $2") // transform personUSA => person USA
|
||||||
|
.replace(/^([A-Z]+)([A-Z])([a-z])/, "$1 $2$3")); // transform USAPerson => USA Person
|
||||||
return (label);
|
return (label);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,12 +61,10 @@ interface QDeleteButtonProps
|
|||||||
export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
|
export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<MDBox ml={3} mr={3}>
|
<MDBox ml={3} mr={3} width={standardWidth}>
|
||||||
<MDBox width={standardWidth}>
|
<MDButton variant="gradient" color="primary" size="small" onClick={onClickHandler} fullWidth startIcon={<Icon>delete</Icon>}>
|
||||||
<MDButton variant="gradient" color="primary" size="small" onClick={onClickHandler} fullWidth startIcon={<Icon>delete</Icon>}>
|
Delete
|
||||||
Delete
|
</MDButton>
|
||||||
</MDButton>
|
|
||||||
</MDBox>
|
|
||||||
</MDBox>
|
</MDBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -74,13 +72,11 @@ export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
|
|||||||
export function QEditButton(): JSX.Element
|
export function QEditButton(): JSX.Element
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<MDBox>
|
<MDBox width={standardWidth}>
|
||||||
<Link to="edit">
|
<Link to="edit">
|
||||||
<MDBox width={standardWidth}>
|
<MDButton variant="gradient" color="dark" size="small" fullWidth startIcon={<Icon>edit</Icon>}>
|
||||||
<MDButton variant="gradient" color="dark" size="small" fullWidth startIcon={<Icon>edit</Icon>}>
|
Edit
|
||||||
Edit
|
</MDButton>
|
||||||
</MDButton>
|
|
||||||
</MDBox>
|
|
||||||
</Link>
|
</Link>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
);
|
);
|
||||||
|
@ -34,7 +34,6 @@ import QDynamicFormField from "qqq/components/QDynamicFormField";
|
|||||||
interface Props {
|
interface Props {
|
||||||
formLabel?: string;
|
formLabel?: string;
|
||||||
formData: any;
|
formData: any;
|
||||||
primaryKeyId?: string;
|
|
||||||
bulkEditMode?: boolean;
|
bulkEditMode?: boolean;
|
||||||
bulkEditSwitchChangeHandler?: any
|
bulkEditSwitchChangeHandler?: any
|
||||||
}
|
}
|
||||||
@ -42,7 +41,7 @@ interface Props {
|
|||||||
function QDynamicForm(props: Props): JSX.Element
|
function QDynamicForm(props: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const {
|
const {
|
||||||
formData, formLabel, primaryKeyId, bulkEditMode, bulkEditSwitchChangeHandler,
|
formData, formLabel, bulkEditMode, bulkEditSwitchChangeHandler,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
formFields, values, errors, touched,
|
formFields, values, errors, touched,
|
||||||
@ -116,7 +115,7 @@ function QDynamicForm(props: Props): JSX.Element
|
|||||||
error={errors[fieldName] && touched[fieldName]}
|
error={errors[fieldName] && touched[fieldName]}
|
||||||
bulkEditMode={bulkEditMode}
|
bulkEditMode={bulkEditMode}
|
||||||
bulkEditSwitchChangeHandler={bulkEditSwitchChanged}
|
bulkEditSwitchChangeHandler={bulkEditSwitchChanged}
|
||||||
success={!errors[fieldName] && touched[fieldName]}
|
success={`${values[fieldName]}` !== "" && !errors[fieldName] && touched[fieldName]}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
@ -129,7 +128,6 @@ function QDynamicForm(props: Props): JSX.Element
|
|||||||
|
|
||||||
QDynamicForm.defaultProps = {
|
QDynamicForm.defaultProps = {
|
||||||
formLabel: undefined,
|
formLabel: undefined,
|
||||||
primaryKeyId: undefined,
|
|
||||||
bulkEditMode: false,
|
bulkEditMode: false,
|
||||||
bulkEditSwitchChangeHandler: () =>
|
bulkEditSwitchChangeHandler: () =>
|
||||||
{},
|
{},
|
||||||
|
@ -26,7 +26,6 @@ import {ErrorMessage, Field} from "formik";
|
|||||||
import MDBox from "components/MDBox";
|
import MDBox from "components/MDBox";
|
||||||
import MDTypography from "components/MDTypography";
|
import MDTypography from "components/MDTypography";
|
||||||
import MDInput from "components/MDInput";
|
import MDInput from "components/MDInput";
|
||||||
import QDynamicForm from "qqq/components/QDynamicForm";
|
|
||||||
import React, {useState} from "react";
|
import React, {useState} from "react";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
|
@ -28,9 +28,10 @@ import MDBox from "components/MDBox";
|
|||||||
import MDTypography from "components/MDTypography";
|
import MDTypography from "components/MDTypography";
|
||||||
import Card from "@mui/material/Card";
|
import Card from "@mui/material/Card";
|
||||||
import {Theme} from "@mui/material/styles";
|
import {Theme} from "@mui/material/styles";
|
||||||
|
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tableSections: any;
|
tableSections: QSection[];
|
||||||
light?: boolean;
|
light?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,11 +41,11 @@ function QRecordSidebar({tableSections, light}: Props): JSX.Element
|
|||||||
<Card sx={{borderRadius: ({borders: {borderRadius}}) => borderRadius.lg, position: "sticky", top: "1%"}}>
|
<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"}}>
|
<MDBox component="ul" display="flex" flexDirection="column" p={2} m={0} sx={{listStyle: "none"}}>
|
||||||
{
|
{
|
||||||
tableSections ? tableSections.map(({icon, label, name}: any, key: number) => (
|
tableSections ? tableSections.map((section: QSection, key: number) => (
|
||||||
<MDBox key={`section-${name}`} component="li" pt={key === 0 ? 0 : 1}>
|
<MDBox key={`section-${section.name}`} component="li" pt={key === 0 ? 0 : 1}>
|
||||||
<MDTypography
|
<MDTypography
|
||||||
component="a"
|
component="a"
|
||||||
href={`#${name}`}
|
href={`#${section.name}`}
|
||||||
variant="button"
|
variant="button"
|
||||||
fontWeight="regular"
|
fontWeight="regular"
|
||||||
sx={({
|
sx={({
|
||||||
@ -65,9 +66,9 @@ function QRecordSidebar({tableSections, light}: Props): JSX.Element
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<MDBox mr={1.5} lineHeight={1} color="black">
|
<MDBox mr={1.5} lineHeight={1} color="black">
|
||||||
<Icon fontSize="small">{icon}</Icon>
|
<Icon fontSize="small">{section.iconName}</Icon>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
{label}
|
{section.label}
|
||||||
</MDTypography>
|
</MDTypography>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
)) : null
|
)) : null
|
||||||
|
@ -29,7 +29,6 @@ import MDBox from "components/MDBox";
|
|||||||
import EntityForm from "qqq/components/EntityForm";
|
import EntityForm from "qqq/components/EntityForm";
|
||||||
import BaseLayout from "qqq/components/BaseLayout";
|
import BaseLayout from "qqq/components/BaseLayout";
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
import {useParams} from "react-router-dom";
|
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
|
@ -134,6 +134,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
const [columnVisibilityModel, setColumnVisibilityModel] = useState(defaultVisibility);
|
const [columnVisibilityModel, setColumnVisibilityModel] = useState(defaultVisibility);
|
||||||
const [gridMouseDownX, setGridMouseDownX] = useState(0);
|
const [gridMouseDownX, setGridMouseDownX] = useState(0);
|
||||||
const [gridMouseDownY, setGridMouseDownY] = useState(0);
|
const [gridMouseDownY, setGridMouseDownY] = useState(0);
|
||||||
|
const [pinnedColumns, setPinnedColumns] = useState({left: ["__check__", "id"]});
|
||||||
const instance = useRef({timer: null});
|
const instance = useRef({timer: null});
|
||||||
|
|
||||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||||
@ -223,6 +224,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
});
|
});
|
||||||
setColumnSortModel(columnSortModel);
|
setColumnSortModel(columnSortModel);
|
||||||
}
|
}
|
||||||
|
setPinnedColumns({left: ["__check__", tableMetaData.primaryKeyField]});
|
||||||
|
|
||||||
const qFilter = buildQFilter();
|
const qFilter = buildQFilter();
|
||||||
|
|
||||||
@ -626,15 +628,8 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
// eslint-disable-next-line react/no-unstable-nested-components
|
// eslint-disable-next-line react/no-unstable-nested-components
|
||||||
function CustomToolbar()
|
function CustomToolbar()
|
||||||
{
|
{
|
||||||
function gtcMouseDown(e: React.MouseEvent<HTMLDivElement>)
|
|
||||||
{
|
|
||||||
console.log(e.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GridToolbarContainer
|
<GridToolbarContainer>
|
||||||
onMouseDown={(e) => gtcMouseDown(e)}
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
id="refresh-button"
|
id="refresh-button"
|
||||||
@ -711,7 +706,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
<MenuItem onClick={bulkLoadClicked}>Bulk Load</MenuItem>
|
<MenuItem onClick={bulkLoadClicked}>Bulk Load</MenuItem>
|
||||||
<MenuItem onClick={bulkEditClicked}>Bulk Edit</MenuItem>
|
<MenuItem onClick={bulkEditClicked}>Bulk Edit</MenuItem>
|
||||||
<MenuItem onClick={bulkDeleteClicked}>Bulk Delete</MenuItem>
|
<MenuItem onClick={bulkDeleteClicked}>Bulk Delete</MenuItem>
|
||||||
<MenuItem divider />
|
{tableProcesses.length > 0 && <MenuItem divider />}
|
||||||
{tableProcesses.map((process) => (
|
{tableProcesses.map((process) => (
|
||||||
<MenuItem key={process.name} onClick={() => processClicked(process)}>{process.label}</MenuItem>
|
<MenuItem key={process.name} onClick={() => processClicked(process)}>{process.label}</MenuItem>
|
||||||
))}
|
))}
|
||||||
@ -759,9 +754,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
<MDBox display="flex" justifyContent="flex-end" alignItems="flex-start" mb={2}>
|
<MDBox display="flex" justifyContent="flex-end" alignItems="flex-start" mb={2}>
|
||||||
|
|
||||||
<MDBox display="flex" width="150px">
|
<MDBox display="flex" width="150px">
|
||||||
{tableProcesses.length > 0 && (
|
<QActionsMenuButton isOpen={actionsMenu} onClickHandler={openActionsMenu} />
|
||||||
<QActionsMenuButton isOpen={actionsMenu} onClickHandler={openActionsMenu} />
|
|
||||||
)}
|
|
||||||
{renderActionsMenu}
|
{renderActionsMenu}
|
||||||
</MDBox>
|
</MDBox>
|
||||||
|
|
||||||
@ -774,7 +767,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
<MDBox height="100%">
|
<MDBox height="100%">
|
||||||
<DataGridPro
|
<DataGridPro
|
||||||
components={{Toolbar: CustomToolbar, Pagination: CustomPagination, LoadingOverlay: Loading}}
|
components={{Toolbar: CustomToolbar, Pagination: CustomPagination, LoadingOverlay: Loading}}
|
||||||
pinnedColumns={{left: ["__check__", "id"]}}
|
initialState={{pinnedColumns: pinnedColumns}}
|
||||||
pagination
|
pagination
|
||||||
paginationMode="server"
|
paginationMode="server"
|
||||||
sortingMode="server"
|
sortingMode="server"
|
||||||
|
@ -52,6 +52,8 @@ import Icon from "@mui/material/Icon";
|
|||||||
import Avatar from "@mui/material/Avatar";
|
import Avatar from "@mui/material/Avatar";
|
||||||
import QRecordSidebar from "qqq/components/QRecordSidebar";
|
import QRecordSidebar from "qqq/components/QRecordSidebar";
|
||||||
import QTableUtils from "qqq/utils/QTableUtils";
|
import QTableUtils from "qqq/utils/QTableUtils";
|
||||||
|
import colors from "assets/theme/base/colors";
|
||||||
|
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||||
|
|
||||||
const qController = QClient.getInstance();
|
const qController = QClient.getInstance();
|
||||||
|
|
||||||
@ -73,11 +75,13 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
const [asyncLoadInited, setAsyncLoadInited] = useState(false);
|
const [asyncLoadInited, setAsyncLoadInited] = useState(false);
|
||||||
const [nameValues, setNameValues] = useState([] as JSX.Element[]);
|
const [nameValues, setNameValues] = useState([] as JSX.Element[]);
|
||||||
const [sectionFieldElements, setSectionFieldElements] = useState(null as Map<string, JSX.Element[]>);
|
const [sectionFieldElements, setSectionFieldElements] = useState(null as Map<string, JSX.Element[]>);
|
||||||
const [t1Section, setT1Section] = useState(null as JSX.Element);
|
const [deleteConfirmationOpen, setDeleteConfirmationOpen] = useState(false);
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [tableMetaData, setTableMetaData] = useState(null);
|
const [tableMetaData, setTableMetaData] = useState(null);
|
||||||
const [record, setRecord] = useState(null as QRecord);
|
const [record, setRecord] = useState(null as QRecord);
|
||||||
const [tableSections, setTableSections] = useState(null as any);
|
const [tableSections, setTableSections] = useState([] as QSection[]);
|
||||||
|
const [t1SectionName, setT1SectionName] = useState(null as string);
|
||||||
|
const [t1SectionElement, setT1SectionElement] = useState(null as JSX.Element);
|
||||||
|
const [nonT1TableSections, setNonT1TableSections] = useState([] as QSection[]);
|
||||||
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
||||||
const [actionsMenu, setActionsMenu] = useState(null);
|
const [actionsMenu, setActionsMenu] = useState(null);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
@ -120,6 +124,7 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
// make elements with the values for each section //
|
// make elements with the values for each section //
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
const sectionFieldElements = new Map();
|
const sectionFieldElements = new Map();
|
||||||
|
const nonT1TableSections = [];
|
||||||
for (let i = 0; i < tableSections.length; i++)
|
for (let i = 0; i < tableSections.length; i++)
|
||||||
{
|
{
|
||||||
const section = tableSections[i];
|
const section = tableSections[i];
|
||||||
@ -145,45 +150,29 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
|
|
||||||
if (section.tier === "T1")
|
if (section.tier === "T1")
|
||||||
{
|
{
|
||||||
setT1Section(sectionFieldElements.get(section.name));
|
setT1SectionElement(sectionFieldElements.get(section.name));
|
||||||
|
setT1SectionName(section.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nonT1TableSections.push(tableSections[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSectionFieldElements(sectionFieldElements);
|
setSectionFieldElements(sectionFieldElements);
|
||||||
|
setNonT1TableSections(nonT1TableSections);
|
||||||
// todo - delete this
|
|
||||||
const sortedKeys = [...record.values.keys()].sort();
|
|
||||||
sortedKeys.forEach((key) =>
|
|
||||||
{
|
|
||||||
if (key !== tableMetaData.primaryKeyField)
|
|
||||||
{
|
|
||||||
nameValues.push(
|
|
||||||
<MDBox key={key} display="flex" py={1} pr={2}>
|
|
||||||
<MDTypography variant="button" fontWeight="bold" textTransform="capitalize">
|
|
||||||
{tableMetaData.fields.get(key).label}
|
|
||||||
:
|
|
||||||
</MDTypography>
|
|
||||||
<MDTypography variant="button" fontWeight="regular" color="text">
|
|
||||||
|
|
||||||
{QValueUtils.getDisplayValue(tableMetaData.fields.get(key), record)}
|
|
||||||
</MDTypography>
|
|
||||||
</MDBox>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setNameValues(nameValues);
|
|
||||||
|
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClickConfirmOpen = () =>
|
const handleClickDeleteButton = () =>
|
||||||
{
|
{
|
||||||
setOpen(true);
|
setDeleteConfirmationOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClickConfirmClose = () =>
|
const handleDeleteConfirmClose = () =>
|
||||||
{
|
{
|
||||||
setOpen(false);
|
setDeleteConfirmationOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (event: { preventDefault: () => void }) =>
|
const handleDelete = (event: { preventDefault: () => void }) =>
|
||||||
@ -225,12 +214,12 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
<MenuItem onClick={() =>
|
<MenuItem onClick={() =>
|
||||||
{
|
{
|
||||||
setActionsMenu(null);
|
setActionsMenu(null);
|
||||||
handleClickConfirmOpen();
|
handleClickDeleteButton();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem divider />
|
{tableProcesses.length > 0 && <MenuItem divider />}
|
||||||
{tableProcesses.map((process) => (
|
{tableProcesses.map((process) => (
|
||||||
<MenuItem key={process.name} onClick={() => processClicked(process)}>{process.label}</MenuItem>
|
<MenuItem key={process.name} onClick={() => processClicked(process)}>{process.label}</MenuItem>
|
||||||
))}
|
))}
|
||||||
@ -261,10 +250,10 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
|
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} mb={3}>
|
<Grid item xs={12} mb={3}>
|
||||||
<Card>
|
<Card id={t1SectionName}>
|
||||||
<MDBox display="flex" p={3} pb={1}>
|
<MDBox display="flex" p={3} pb={1}>
|
||||||
<MDBox mr={1.5}>
|
<MDBox mr={1.5}>
|
||||||
<Avatar sx={{bgcolor: "rgb(26, 115, 232)"}}>
|
<Avatar sx={{bgcolor: colors.info.main}}>
|
||||||
<Icon>
|
<Icon>
|
||||||
{tableMetaData?.iconName}
|
{tableMetaData?.iconName}
|
||||||
</Icon>
|
</Icon>
|
||||||
@ -274,33 +263,29 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
<MDTypography variant="h5">
|
<MDTypography variant="h5">
|
||||||
{tableMetaData && record ? `Viewing ${tableMetaData?.label}: ${record?.recordLabel}` : ""}
|
{tableMetaData && record ? `Viewing ${tableMetaData?.label}: ${record?.recordLabel}` : ""}
|
||||||
</MDTypography>
|
</MDTypography>
|
||||||
{tableProcesses.length > 0 && (
|
<QActionsMenuButton isOpen={actionsMenu} onClickHandler={openActionsMenu} />
|
||||||
<QActionsMenuButton isOpen={actionsMenu} onClickHandler={openActionsMenu} />
|
|
||||||
)}
|
|
||||||
{renderActionsMenu}
|
{renderActionsMenu}
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
{t1Section ? (<MDBox p={3} pt={0}>{t1Section}</MDBox>) : null}
|
{t1SectionElement ? (<MDBox p={3} pt={0}>{t1SectionElement}</MDBox>) : null}
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{tableSections && sectionFieldElements ? tableSections.map(({
|
{nonT1TableSections.length > 0 ? nonT1TableSections.map(({
|
||||||
icon, label, name, fieldNames, tier,
|
iconName, label, name, fieldNames, tier,
|
||||||
}: any) => (tier !== "T1"
|
}: any) => (
|
||||||
? (
|
<MDBox mb={3} key={name}>
|
||||||
<MDBox mb={3} key={name}>
|
<Card key={name} id={name} sx={{overflow: "visible"}}>
|
||||||
<Card key={name} id={name} sx={{overflow: "visible"}}>
|
<MDTypography variant="h5" p={3} pb={1}>
|
||||||
<MDTypography variant="h5" p={3} pb={1}>
|
{label}
|
||||||
{label}
|
</MDTypography>
|
||||||
</MDTypography>
|
<MDBox p={3} pt={0} flexDirection="column">{sectionFieldElements.get(name)}</MDBox>
|
||||||
<MDBox p={3} pt={0} flexDirection="column">{sectionFieldElements.get(name)}</MDBox>
|
</Card>
|
||||||
</Card>
|
</MDBox>
|
||||||
</MDBox>
|
)) : null}
|
||||||
) : null)) : null}
|
|
||||||
|
|
||||||
<MDBox component="form" p={3}>
|
<MDBox component="form" p={3}>
|
||||||
<Grid container justifyContent="flex-end" spacing={3}>
|
<Grid container justifyContent="flex-end" spacing={3}>
|
||||||
<QDeleteButton onClickHandler={handleClickConfirmOpen} />
|
<QDeleteButton onClickHandler={handleClickDeleteButton} />
|
||||||
<QEditButton />
|
<QEditButton />
|
||||||
</Grid>
|
</Grid>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
@ -310,8 +295,8 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
|
|
||||||
{/* Delete confirmation Dialog */}
|
{/* Delete confirmation Dialog */}
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={deleteConfirmationOpen}
|
||||||
onClose={handleClickConfirmClose}
|
onClose={handleDeleteConfirmClose}
|
||||||
aria-labelledby="alert-dialog-title"
|
aria-labelledby="alert-dialog-title"
|
||||||
aria-describedby="alert-dialog-description"
|
aria-describedby="alert-dialog-description"
|
||||||
>
|
>
|
||||||
@ -322,7 +307,7 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClickConfirmClose}>No</Button>
|
<Button onClick={handleDeleteConfirmClose}>No</Button>
|
||||||
<Button onClick={handleDelete} autoFocus>
|
<Button onClick={handleDelete} autoFocus>
|
||||||
Yes
|
Yes
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -81,7 +81,8 @@
|
|||||||
/* shrink font on in the pagination control */
|
/* shrink font on in the pagination control */
|
||||||
.MuiTablePagination-displayedRows,
|
.MuiTablePagination-displayedRows,
|
||||||
.MuiTablePagination-selectLabel,
|
.MuiTablePagination-selectLabel,
|
||||||
.MuiTablePagination-select.MuiSelect-select.MuiSelect-standard
|
.MuiTablePagination-select.MuiSelect-select.MuiSelect-standard,
|
||||||
|
.MuiDataGrid-selectedRowCount
|
||||||
{
|
{
|
||||||
font-size: 0.85rem !important;
|
font-size: 0.85rem !important;
|
||||||
}
|
}
|
||||||
@ -93,14 +94,8 @@
|
|||||||
border-radius: 5px !important;
|
border-radius: 5px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hide the selected row count (we show our own) */
|
|
||||||
.MuiDataGrid-selectedRowCount
|
|
||||||
{
|
|
||||||
visibility: hidden !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* move the green check / red x down to align with the calendar icon */
|
/* move the green check / red x down to align with the calendar icon */
|
||||||
.MuiFormControl-root
|
.MuiFormControl-root
|
||||||
{
|
{
|
||||||
background-position-y: 1.4rem;
|
background-position-y: 1.4rem !important;
|
||||||
}
|
}
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
|
import {QSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QSection";
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Utility class for working with QQQ Tables
|
** Utility class for working with QQQ Tables
|
||||||
@ -27,27 +28,18 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QT
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
class QTableUtils
|
class QTableUtils
|
||||||
{
|
{
|
||||||
public static getSectionsForRecordSidebar(tableMetaData: QTableMetaData): any
|
public static getSectionsForRecordSidebar(tableMetaData: QTableMetaData): QSection[]
|
||||||
{
|
{
|
||||||
const tableSections = [];
|
|
||||||
if (tableMetaData.sections)
|
if (tableMetaData.sections)
|
||||||
{
|
{
|
||||||
for (let i = 0; i < tableMetaData.sections.length; i++)
|
return (tableMetaData.sections);
|
||||||
{
|
|
||||||
const section = tableMetaData.sections[i];
|
|
||||||
tableSections.push({
|
|
||||||
icon: section.iconName, label: section.label, name: section.name, fieldNames: section.fieldNames, tier: section.tier,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tableSections.push({
|
return ([new QSection({
|
||||||
icon: "description", label: "All Fields", name: "allFields", fieldNames: [...tableMetaData.fields.keys()],
|
iconName: "description", label: "All Fields", name: "allFields", fieldNames: [...tableMetaData.fields.keys()],
|
||||||
});
|
})]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tableSections);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user