mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-22 07:08:44 +00:00
Compare commits
2 Commits
snapshot-f
...
snapshot-i
Author | SHA1 | Date | |
---|---|---|---|
ce9ffaab4d | |||
9816403bec |
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,7 +5,6 @@
|
||||
.yalc*
|
||||
yalc.lock
|
||||
.env
|
||||
/certs
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
@ -6,7 +6,7 @@
|
||||
"@auth0/auth0-react": "1.10.2",
|
||||
"@emotion/react": "11.7.1",
|
||||
"@emotion/styled": "11.6.0",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.119",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.114",
|
||||
"@mui/icons-material": "5.4.1",
|
||||
"@mui/material": "5.11.1",
|
||||
"@mui/styles": "5.11.1",
|
||||
|
4
pom.xml
4
pom.xml
@ -29,7 +29,7 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<revision>0.25.0-SNAPSHOT</revision>
|
||||
<revision>0.24.0-SNAPSHOT</revision>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
@ -66,7 +66,7 @@
|
||||
<dependency>
|
||||
<groupId>com.kingsrook.qqq</groupId>
|
||||
<artifactId>qqq-backend-core</artifactId>
|
||||
<version>0.25.0-integration-sprint-62-20250307-205536</version>
|
||||
<version>0.21.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
20
src/App.tsx
20
src/App.tsx
@ -29,7 +29,6 @@ import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstan
|
||||
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
import Box from "@mui/material/Box";
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import {ThemeProvider} from "@mui/material/styles";
|
||||
@ -39,7 +38,6 @@ import jwt_decode from "jwt-decode";
|
||||
import QContext from "QContext";
|
||||
import Sidenav from "qqq/components/horseshoe/sidenav/SideNav";
|
||||
import theme from "qqq/components/legacy/Theme";
|
||||
import {getBannerClassName, getBannerStyles, getBanner, makeBannerContent} from "qqq/components/misc/Banners";
|
||||
import {setMiniSidenav, setOpenConfigurator, useMaterialUIController} from "qqq/context";
|
||||
import AppHome from "qqq/pages/apps/Home";
|
||||
import NoApps from "qqq/pages/apps/NoApps";
|
||||
@ -693,23 +691,6 @@ export default function App()
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
function banner(): JSX.Element | null
|
||||
{
|
||||
const banner = getBanner(metaData?.branding, "QFMD_TOP_OF_SITE");
|
||||
|
||||
if (!banner)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
|
||||
return (<Box className={getBannerClassName(banner)} sx={{display: "flex", justifyContent: "center", padding: "0.5rem", position: "sticky", top: "0", zIndex: 1, ...getBannerStyles(banner)}}>
|
||||
{makeBannerContent(banner)}
|
||||
</Box>);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
appRoutes && (
|
||||
@ -737,7 +718,6 @@ export default function App()
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<CommandMenu metaData={metaData} />
|
||||
{banner()}
|
||||
<Sidenav
|
||||
color={sidenavColor}
|
||||
icon={branding.icon}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2025. 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/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.frontend.materialdashboard.model.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.branding.BannerSlot;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public enum MaterialDashboardBannerSlots implements BannerSlot
|
||||
{
|
||||
QFMD_TOP_OF_SITE,
|
||||
QFMD_TOP_OF_BODY,
|
||||
QFMD_SIDE_NAV_UNDER_LOGO
|
||||
}
|
@ -96,7 +96,6 @@ function QDynamicForm({formData, formLabel, bulkEditMode, bulkEditSwitchChangeHa
|
||||
if (width == "full")
|
||||
{
|
||||
itemSM = 12;
|
||||
itemLG = 12;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -270,7 +270,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
|
||||
{
|
||||
pageHeader &&
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
<MDTypography pb="0.5rem" variant="h3" color={light ? "white" : "dark"} noWrap>
|
||||
<MDTypography pb="0.5rem" textTransform="capitalize" variant="h3" color={light ? "white" : "dark"} noWrap>
|
||||
{pageHeader}
|
||||
</MDTypography>
|
||||
</Box>
|
||||
|
@ -34,7 +34,6 @@ import SideNavList from "qqq/components/horseshoe/sidenav/SideNavList";
|
||||
import SidenavRoot from "qqq/components/horseshoe/sidenav/SideNavRoot";
|
||||
import sidenavLogoLabel from "qqq/components/horseshoe/sidenav/styles/SideNav";
|
||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||
import {getBannerClassName, getBannerStyles, getBanner, makeBannerContent} from "qqq/components/misc/Banners";
|
||||
import {setMiniSidenav, setTransparentSidenav, setWhiteSidenav, useMaterialUIController,} from "qqq/context";
|
||||
|
||||
|
||||
@ -301,30 +300,6 @@ function Sidenav({color, icon, logo, appName, branding, routes, ...rest}: Props)
|
||||
}
|
||||
);
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
function EnvironmentBanner({branding}: { branding: QBrandingMetaData }): JSX.Element | null
|
||||
{
|
||||
// deprecated!
|
||||
if (branding && branding.environmentBannerText)
|
||||
{
|
||||
return <Box mt={2} bgcolor={branding.environmentBannerColor} borderRadius={2}>
|
||||
{branding.environmentBannerText}
|
||||
</Box>;
|
||||
}
|
||||
|
||||
const banner = getBanner(branding, "QFMD_SIDE_NAV_UNDER_LOGO");
|
||||
if (banner)
|
||||
{
|
||||
return <Box className={getBannerClassName(banner)} mt={2} borderRadius={2} sx={getBannerStyles(banner)}>
|
||||
{makeBannerContent(banner)}
|
||||
</Box>;
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidenavRoot
|
||||
{...rest}
|
||||
@ -355,7 +330,12 @@ function Sidenav({color, icon, logo, appName, branding, routes, ...rest}: Props)
|
||||
</Box>
|
||||
}
|
||||
</Box>
|
||||
<EnvironmentBanner branding={branding} />
|
||||
{
|
||||
branding && branding.environmentBannerText &&
|
||||
<Box mt={2} bgcolor={branding.environmentBannerColor} borderRadius={2}>
|
||||
{branding.environmentBannerText}
|
||||
</Box>
|
||||
}
|
||||
</Box>
|
||||
<Divider
|
||||
light={
|
||||
|
@ -97,7 +97,6 @@ export default styled(Drawer)(({theme, ownerState}: { theme?: Theme | any; owner
|
||||
margin: "0",
|
||||
borderRadius: "0",
|
||||
height: "100%",
|
||||
top: "unset",
|
||||
|
||||
...(miniSidenav ? drawerCloseStyles() : drawerOpenStyles()),
|
||||
},
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2025. 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 {Banner} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Banner";
|
||||
import {QBrandingMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QBrandingMetaData";
|
||||
import parse from "html-react-parser";
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// One may render a banner using the functions in this file as: //
|
||||
// //
|
||||
// const banner = getBanner(branding, "QFMD_SIDE_NAV_UNDER_LOGO"); //
|
||||
// return (<Box className={getBannerClassName(banner)} sx={{padding: "1rem", ...getBannerStyles(banner)}}> //
|
||||
// {makeBannerContent(banner)} //
|
||||
// </Box>); //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
export function getBanner(branding: QBrandingMetaData, slot: string): Banner | null
|
||||
{
|
||||
if (branding?.banners?.has(slot))
|
||||
{
|
||||
return (branding.banners.get(slot));
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
export function getBannerStyles(banner: Banner)
|
||||
{
|
||||
let bgColor = "";
|
||||
let color = "";
|
||||
|
||||
if (banner)
|
||||
{
|
||||
if (banner.backgroundColor)
|
||||
{
|
||||
bgColor = banner.backgroundColor;
|
||||
}
|
||||
|
||||
if (banner.textColor)
|
||||
{
|
||||
bgColor = banner.textColor;
|
||||
}
|
||||
}
|
||||
|
||||
const rest = banner?.additionalStyles ?? {};
|
||||
|
||||
return ({
|
||||
backgroundColor: bgColor,
|
||||
color: color,
|
||||
...rest
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
export function getBannerClassName(banner: Banner)
|
||||
{
|
||||
return `banner ${banner?.severity?.toLowerCase()}`;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
export function makeBannerContent(banner: Banner): JSX.Element
|
||||
{
|
||||
return <>{banner?.messageHTML ? parse(banner?.messageHTML) : banner?.messageText}</>;
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
|
||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import {QTableVariant} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableVariant";
|
||||
@ -36,11 +35,12 @@ import DialogTitle from "@mui/material/DialogTitle";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import {any} from "prop-types";
|
||||
import React, {useState} from "react";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {QCancelButton} from "qqq/components/buttons/DefaultButtons";
|
||||
import MDButton from "qqq/components/legacy/MDButton";
|
||||
import Client from "qqq/utils/qqq/Client";
|
||||
import React, {useState} from "react";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
|
||||
interface Props
|
||||
{
|
||||
@ -186,14 +186,14 @@ function GotoRecordDialog(props: Props): JSX.Element
|
||||
{
|
||||
anyFieldsInThisOptionHaveAValue = true;
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if(!anyFieldsInThisOptionHaveAValue)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
@ -207,13 +207,9 @@ function GotoRecordDialog(props: Props): JSX.Element
|
||||
const queryStringParts: string[] = [];
|
||||
options[optionIndex].forEach((field) =>
|
||||
{
|
||||
if (field.type == QFieldType.STRING && !values[field.name][0])
|
||||
{
|
||||
return;
|
||||
}
|
||||
criteria.push(new QFilterCriteria(field.name, QCriteriaOperator.EQUALS, [values[field.name]]));
|
||||
queryStringParts.push(`${field.name}=${encodeURIComponent(values[field.name])}`);
|
||||
});
|
||||
criteria.push(new QFilterCriteria(field.name, QCriteriaOperator.EQUALS, [values[field.name]]))
|
||||
queryStringParts.push(`${field.name}=${encodeURIComponent(values[field.name])}`)
|
||||
})
|
||||
|
||||
const filter = new QQueryFilter(criteria, null, null, "AND", null, 10);
|
||||
|
||||
|
@ -109,7 +109,6 @@ export const getOperatorOptions = (tableMetaData: QTableMetaData, fieldName: str
|
||||
{
|
||||
case QFieldType.DECIMAL:
|
||||
case QFieldType.INTEGER:
|
||||
case QFieldType.LONG:
|
||||
operatorOptions.push({label: "equals", value: QCriteriaOperator.EQUALS, valueMode: ValueMode.SINGLE});
|
||||
operatorOptions.push({label: "does not equal", value: QCriteriaOperator.NOT_EQUALS_OR_IS_NULL, valueMode: ValueMode.SINGLE});
|
||||
operatorOptions.push({label: "greater than", value: QCriteriaOperator.GREATER_THAN, valueMode: ValueMode.SINGLE});
|
||||
|
@ -111,7 +111,7 @@ function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRo
|
||||
}
|
||||
|
||||
const tableMetaData = data.childTableMetaData instanceof QTableMetaData ? data.childTableMetaData as QTableMetaData : new QTableMetaData(data.childTableMetaData);
|
||||
const rows = DataGridUtils.makeRows(records, tableMetaData, undefined, true);
|
||||
const rows = DataGridUtils.makeRows(records, tableMetaData, true);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// note - tablePath may be null, if the user doesn't have access to the table. //
|
||||
@ -255,7 +255,7 @@ function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRo
|
||||
disabledFields = data.defaultValuesForNewChildRecords;
|
||||
}
|
||||
|
||||
const defaultValuesForNewChildRecords = data.defaultValuesForNewChildRecords || {};
|
||||
const defaultValuesForNewChildRecords = data.defaultValuesForNewChildRecords || {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// copy values from specified fields in the parent record down into the child record //
|
||||
|
@ -21,12 +21,11 @@
|
||||
|
||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||
import Box from "@mui/material/Box";
|
||||
import {ReactNode, useEffect, useState} from "react";
|
||||
import Footer from "qqq/components/horseshoe/Footer";
|
||||
import NavBar from "qqq/components/horseshoe/NavBar";
|
||||
import {getBannerClassName, getBannerStyles, getBanner, makeBannerContent} from "qqq/components/misc/Banners";
|
||||
import DashboardLayout from "qqq/layouts/DashboardLayout";
|
||||
import Client from "qqq/utils/qqq/Client";
|
||||
import {ReactNode, useEffect, useState} from "react";
|
||||
|
||||
interface Props
|
||||
{
|
||||
@ -81,34 +80,12 @@ function BaseLayout({stickyNavbar, children}: Props): JSX.Element
|
||||
return () => window.removeEventListener("resize", handleTabsOrientation);
|
||||
}, [tabsOrientation]);
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
function banner(): JSX.Element | null
|
||||
{
|
||||
const banner = getBanner(metaData?.branding, "QFMD_TOP_OF_BODY");
|
||||
|
||||
if (!banner)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
|
||||
return (<Box className={getBannerClassName(banner)} sx={{display: "flex", justifyContent: "center", padding: "0.5rem", margin: "-20px", marginBottom: "20px", ...getBannerStyles(banner)}}>
|
||||
{makeBannerContent(banner)}
|
||||
</Box>);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<DashboardLayout>
|
||||
{banner()}
|
||||
<NavBar />
|
||||
<Box>{children}</Box>
|
||||
<Footer company={{href: metaData?.branding?.companyUrl, name: metaData?.branding?.companyName}} />
|
||||
</DashboardLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1838,20 +1838,6 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
return;
|
||||
}
|
||||
|
||||
if(urlSearchParams.get("defaultProcessValues"))
|
||||
{
|
||||
if(!defaultProcessValues)
|
||||
{
|
||||
defaultProcessValues = {}
|
||||
}
|
||||
|
||||
const values = JSON.parse(urlSearchParams.get("defaultProcessValues"));
|
||||
for (let key in values)
|
||||
{
|
||||
defaultProcessValues[key] = values[key]
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultProcessValues)
|
||||
{
|
||||
for (let key in defaultProcessValues)
|
||||
|
@ -1103,7 +1103,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, isPreview, allowVariable
|
||||
////////////////////////////////
|
||||
// make the rows for the grid //
|
||||
////////////////////////////////
|
||||
const rows = DataGridUtils.makeRows(results, tableMetaData, tableVariant);
|
||||
const rows = DataGridUtils.makeRows(results, tableMetaData);
|
||||
setRows(rows);
|
||||
|
||||
setLoading(false);
|
||||
@ -1612,22 +1612,6 @@ const RecordQuery = forwardRef(({table, usage, isModal, isPreview, allowVariable
|
||||
*******************************************************************************/
|
||||
const processClicked = (process: QProcessMetaData) =>
|
||||
{
|
||||
if (process.minInputRecords != null && process.minInputRecords > 0 && getNoOfSelectedRecords() === 0)
|
||||
{
|
||||
setAlertContent(`No records were selected for the process: ${process.label}`);
|
||||
return;
|
||||
}
|
||||
else if (process.minInputRecords != null && getNoOfSelectedRecords() < process.minInputRecords)
|
||||
{
|
||||
setAlertContent(`Too few records were selected for the process: ${process.label}. A minimum of ${process.minInputRecords} is required.`);
|
||||
return;
|
||||
}
|
||||
else if (process.maxInputRecords != null && getNoOfSelectedRecords() > process.maxInputRecords)
|
||||
{
|
||||
setAlertContent(`Too many records were selected for the process: ${process.label}. A maximum of ${process.maxInputRecords} is allowed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// todo - let the process specify that it needs initial rows - err if none selected.
|
||||
// alternatively, let a process itself have an initial screen to select rows...
|
||||
openModalProcess(process);
|
||||
|
@ -92,7 +92,7 @@ const TABLE_VARIANT_LOCAL_STORAGE_KEY_ROOT = "qqq.tableVariant";
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
export function renderSectionOfFields(key: string, fieldNames: string[], tableMetaData: QTableMetaData, helpHelpActive: boolean, record: QRecord, fieldMap?: { [name: string]: QFieldMetaData }, styleOverrides?: {label?: SxProps, value?: SxProps}, tableVariant?: QTableVariant)
|
||||
export function renderSectionOfFields(key: string, fieldNames: string[], tableMetaData: QTableMetaData, helpHelpActive: boolean, record: QRecord, fieldMap?: { [name: string]: QFieldMetaData }, styleOverrides?: { label?: SxProps, value?: SxProps })
|
||||
{
|
||||
return <Grid container lg={12} key={key} display="flex" py={1} pr={2}>
|
||||
{
|
||||
@ -119,7 +119,7 @@ export function renderSectionOfFields(key: string, fieldNames: string[], tableMe
|
||||
}
|
||||
<div style={{display: "inline-block", width: 0}}> </div>
|
||||
<Typography variant="button" textTransform="none" fontWeight="regular" color="rgb(123, 128, 154)" sx={{...(styleOverrides?.value ?? {})}}>
|
||||
{ValueUtils.getDisplayValue(field, record, "view", fieldName, tableVariant)}
|
||||
{ValueUtils.getDisplayValue(field, record, "view", fieldName)}
|
||||
</Typography>
|
||||
</>
|
||||
</Grid>
|
||||
@ -598,7 +598,7 @@ function RecordView({table, record: overrideRecord, launchProcess}: Props): JSX.
|
||||
// for a section with field names, render the field values. //
|
||||
// for the T1 section, the "wrapper" will come out below - but for other sections, produce a wrapper too. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const fields = renderSectionOfFields(section.name, section.fieldNames, tableMetaData, helpHelpActive, record, undefined, undefined, tableVariant);
|
||||
const fields = renderSectionOfFields(section.name, section.fieldNames, tableMetaData, helpHelpActive, record);
|
||||
|
||||
if (section.tier === "T1")
|
||||
{
|
||||
|
@ -748,54 +748,35 @@ input[type="search"]::-webkit-search-results-decoration
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.helpContentAlert.info,
|
||||
.banner.info
|
||||
{
|
||||
background-color: rgb(234, 242, 255);
|
||||
color: rgb(20, 51, 102);
|
||||
}
|
||||
|
||||
.helpContentAlert.info .MuiAlert-icon .material-icons-round,
|
||||
.banner.info .MuiAlert-icon .material-icons-round
|
||||
{
|
||||
color: #0062FF;
|
||||
}
|
||||
|
||||
.helpContentAlert.success,
|
||||
.banner.success
|
||||
.helpContentAlert.success
|
||||
{
|
||||
background-color: rgb(240, 248, 241);
|
||||
color: rgb(44, 76, 46);
|
||||
}
|
||||
|
||||
.helpContentAlert.success .MuiAlert-icon .material-icons-round,
|
||||
.banner.success .MuiAlert-icon .material-icons-round
|
||||
.helpContentAlert.success .MuiAlert-icon .material-icons-round
|
||||
{
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.helpContentAlert.warning,
|
||||
.banner.warning
|
||||
.helpContentAlert.warning
|
||||
{
|
||||
background-color: rgb(254, 245, 234);
|
||||
color: rgb(100, 65, 20);
|
||||
}
|
||||
|
||||
.helpContentAlert.warning .MuiAlert-icon .material-icons-round,
|
||||
.banner.warning .MuiAlert-icon .material-icons-round
|
||||
.helpContentAlert.warning .MuiAlert-icon .material-icons-round
|
||||
{
|
||||
color: #fb8c00;
|
||||
}
|
||||
|
||||
.helpContentAlert.error,
|
||||
.banner.error
|
||||
.helpContentAlert.error
|
||||
{
|
||||
background-color: rgb(254, 239, 238);
|
||||
color: rgb(98, 41, 37);
|
||||
}
|
||||
|
||||
.helpContentAlert.error .MuiAlert-icon .material-icons-round,
|
||||
.banner.error .MuiAlert-icon .material-icons-round
|
||||
.helpContentAlert.error .MuiAlert-icon .material-icons-round
|
||||
{
|
||||
color: #F44335;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QF
|
||||
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
|
||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import {QTableVariant} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableVariant";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import Tooltip from "@mui/material/Tooltip/Tooltip";
|
||||
import {GridColDef, GridRowsProp, MuiEvent} from "@mui/x-data-grid-pro";
|
||||
@ -71,7 +70,7 @@ export default class DataGridUtils
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static makeRows = (results: QRecord[], tableMetaData: QTableMetaData, tableVariant?: QTableVariant, allowEmptyId = false): GridRowsProp[] =>
|
||||
public static makeRows = (results: QRecord[], tableMetaData: QTableMetaData, allowEmptyId = false): GridRowsProp[] =>
|
||||
{
|
||||
const fields = [...tableMetaData.fields.values()];
|
||||
const rows = [] as any[];
|
||||
@ -83,7 +82,7 @@ export default class DataGridUtils
|
||||
|
||||
fields.forEach((field) =>
|
||||
{
|
||||
row[field.name] = ValueUtils.getDisplayValue(field, record, "query", undefined, tableVariant);
|
||||
row[field.name] = ValueUtils.getDisplayValue(field, record, "query");
|
||||
});
|
||||
|
||||
if (tableMetaData.exposedJoins)
|
||||
@ -98,7 +97,7 @@ export default class DataGridUtils
|
||||
fields.forEach((field) =>
|
||||
{
|
||||
let fieldName = join.joinTable.name + "." + field.name;
|
||||
row[fieldName] = ValueUtils.getDisplayValue(field, record, "query", fieldName, tableVariant);
|
||||
row[fieldName] = ValueUtils.getDisplayValue(field, record, "query", fieldName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import {AdornmentType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Ado
|
||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
|
||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||
import {QTableVariant} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableVariant";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import "datejs"; // https://github.com/datejs/Datejs
|
||||
import {Chip, ClickAwayListener, Icon} from "@mui/material";
|
||||
@ -77,14 +76,14 @@ class ValueUtils
|
||||
** When you have a field, and a record - call this method to get a string or
|
||||
** element back to display the field's value.
|
||||
*******************************************************************************/
|
||||
public static getDisplayValue(field: QFieldMetaData, record: QRecord, usage: "view" | "query" = "view", overrideFieldName?: string, tableVariant?: QTableVariant): string | JSX.Element | JSX.Element[]
|
||||
public static getDisplayValue(field: QFieldMetaData, record: QRecord, usage: "view" | "query" = "view", overrideFieldName?: string): string | JSX.Element | JSX.Element[]
|
||||
{
|
||||
const fieldName = overrideFieldName ?? field.name;
|
||||
|
||||
const displayValue = record.displayValues ? record.displayValues.get(fieldName) : undefined;
|
||||
const rawValue = record.values ? record.values.get(fieldName) : undefined;
|
||||
|
||||
return ValueUtils.getValueForDisplay(field, rawValue, displayValue, usage, tableVariant, record, fieldName);
|
||||
return ValueUtils.getValueForDisplay(field, rawValue, displayValue, usage);
|
||||
}
|
||||
|
||||
|
||||
@ -92,35 +91,14 @@ class ValueUtils
|
||||
** When you have a field and a value (either just a raw value, or a raw and
|
||||
** display value), call this method to get a string Element to display.
|
||||
*******************************************************************************/
|
||||
public static getValueForDisplay(field: QFieldMetaData, rawValue: any, displayValue: any = rawValue, usage: "view" | "query" = "view", tableVariant?: QTableVariant, record?: QRecord, fieldName?: string): string | JSX.Element | JSX.Element[]
|
||||
public static getValueForDisplay(field: QFieldMetaData, rawValue: any, displayValue: any = rawValue, usage: "view" | "query" = "view"): string | JSX.Element | JSX.Element[]
|
||||
{
|
||||
if (field.hasAdornment(AdornmentType.LINK))
|
||||
{
|
||||
const adornment = field.getAdornment(AdornmentType.LINK);
|
||||
let href = String(rawValue);
|
||||
|
||||
let toRecordFromTable = adornment.getValue("toRecordFromTable");
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the link adornment has a 'toRecordFromTableDynamic', then look for a display //
|
||||
// value named `fieldName`:toRecordFromTableDynamic for the table name. //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
if(adornment.getValue("toRecordFromTableDynamic"))
|
||||
{
|
||||
const toRecordFromTableDynamic = record?.displayValues?.get(fieldName + ":toRecordFromTableDynamic");
|
||||
if(toRecordFromTableDynamic)
|
||||
{
|
||||
toRecordFromTable = toRecordFromTableDynamic;
|
||||
}
|
||||
else
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// if the table name isn't known, then return w/o the adornment. //
|
||||
///////////////////////////////////////////////////////////////////
|
||||
return (ValueUtils.getUnadornedValueForDisplay(field, rawValue, displayValue));
|
||||
}
|
||||
}
|
||||
let href = rawValue;
|
||||
|
||||
const toRecordFromTable = adornment.getValue("toRecordFromTable");
|
||||
if (toRecordFromTable)
|
||||
{
|
||||
if (ValueUtils.getQInstance())
|
||||
@ -129,7 +107,7 @@ class ValueUtils
|
||||
if (!tablePath)
|
||||
{
|
||||
console.log("Couldn't find path for table: " + toRecordFromTable);
|
||||
return (ValueUtils.getUnadornedValueForDisplay(field, rawValue, displayValue));
|
||||
return (displayValue ?? rawValue);
|
||||
}
|
||||
|
||||
if (!tablePath.endsWith("/"))
|
||||
@ -221,44 +199,12 @@ class ValueUtils
|
||||
|
||||
if (field.type == QFieldType.BLOB || field.hasAdornment(AdornmentType.FILE_DOWNLOAD))
|
||||
{
|
||||
let url = rawValue;
|
||||
if(tableVariant)
|
||||
{
|
||||
url += "?tableVariant=" + encodeURIComponent(JSON.stringify(tableVariant));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// if the field has the download adornment with a downloadUrlDynamic value, //
|
||||
// then get the url from a displayValue of `fieldName`:downloadUrlDynamic. //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
if(field.hasAdornment(AdornmentType.FILE_DOWNLOAD))
|
||||
{
|
||||
const adornment = field.getAdornment(AdornmentType.FILE_DOWNLOAD);
|
||||
let downloadUrlDynamicAdornmentValue = adornment.getValue("downloadUrlDynamic");
|
||||
if(downloadUrlDynamicAdornmentValue)
|
||||
{
|
||||
const downloadUrlDynamicValue = record?.displayValues?.get(fieldName + ":downloadUrlDynamic");
|
||||
if (downloadUrlDynamicValue)
|
||||
{
|
||||
url = downloadUrlDynamicValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// if the url isn't available, then return w/o the adornment. //
|
||||
////////////////////////////////////////////////////////////////
|
||||
return (ValueUtils.getUnadornedValueForDisplay(field, rawValue, displayValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (<BlobComponent field={field} url={url} filename={displayValue} usage={usage} />);
|
||||
return (<BlobComponent field={field} url={rawValue} filename={displayValue} usage={usage} />);
|
||||
}
|
||||
|
||||
return (ValueUtils.getUnadornedValueForDisplay(field, rawValue, displayValue));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** After we know there's no element to be returned (e.g., because no adornment),
|
||||
** this method does the string formatting.
|
||||
|
Reference in New Issue
Block a user