mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-21 22:58:43 +00:00
Compare commits
10 Commits
snapshot-f
...
snapshot-f
Author | SHA1 | Date | |
---|---|---|---|
39a7aadd3f | |||
167af989d5 | |||
ad7ea994a8 | |||
e925310173 | |||
8ebc2415fe | |||
88a4c17bbc | |||
2900cd8593 | |||
8ab0f5f549 | |||
8cffbbcac4 | |||
37eb280d79 |
@ -7,7 +7,7 @@ orbs:
|
||||
executors:
|
||||
java17:
|
||||
docker:
|
||||
- image: 'cimg/openjdk:17.0'
|
||||
- image: 'cimg/openjdk:17.0.9'
|
||||
|
||||
commands:
|
||||
install_java17:
|
||||
|
@ -36,7 +36,7 @@ import Icon from "@mui/material/Icon";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import {makeStyles} from "@mui/styles";
|
||||
import {Command} from "cmdk";
|
||||
import React, {useContext, useEffect, useRef, useState} from "react";
|
||||
import React, {useContext, useEffect, useRef} from "react";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import QContext from "QContext";
|
||||
import HistoryUtils, {QHistoryEntry} from "qqq/utils/HistoryUtils";
|
||||
@ -174,7 +174,9 @@ const CommandMenu = ({metaData}: Props) =>
|
||||
})
|
||||
tableNames = tableNames.sort((a: string, b:string) =>
|
||||
{
|
||||
return (metaData.tables.get(a).label.localeCompare(metaData.tables.get(b).label));
|
||||
const labelA = metaData.tables.get(a).label ?? "";
|
||||
const labelB = metaData.tables.get(b).label ?? "";
|
||||
return (labelA.localeCompare(labelB));
|
||||
})
|
||||
|
||||
const path = location.pathname;
|
||||
@ -222,7 +224,9 @@ const CommandMenu = ({metaData}: Props) =>
|
||||
})
|
||||
tableNames = tableNames.sort((a: string, b:string) =>
|
||||
{
|
||||
return (metaData.tables.get(a).label.localeCompare(metaData.tables.get(b).label));
|
||||
const labelA = metaData.tables.get(a).label ?? "";
|
||||
const labelB = metaData.tables.get(b).label ?? "";
|
||||
return (labelA.localeCompare(labelB));
|
||||
})
|
||||
return(
|
||||
<Command.Group heading="Tables">
|
||||
@ -252,7 +256,9 @@ const CommandMenu = ({metaData}: Props) =>
|
||||
|
||||
appNames = appNames.sort((a: string, b:string) =>
|
||||
{
|
||||
return (getFullAppLabel(metaData.appTree, a, 1, "").localeCompare(getFullAppLabel(metaData.appTree, b, 1, "")));
|
||||
const labelA = getFullAppLabel(metaData.appTree, a, 1, "") ?? "";
|
||||
const labelB = getFullAppLabel(metaData.appTree, b, 1, "") ?? "";
|
||||
return (labelA.localeCompare(labelB));
|
||||
})
|
||||
|
||||
return(
|
||||
@ -286,7 +292,9 @@ const CommandMenu = ({metaData}: Props) =>
|
||||
|
||||
appNames = appNames.sort((a: string, b:string) =>
|
||||
{
|
||||
return (metaData.apps.get(a).label.localeCompare(metaData.apps.get(b).label));
|
||||
const labelA = metaData.apps.get(a).label ?? "";
|
||||
const labelB = metaData.apps.get(b).label ?? "";
|
||||
return (labelA.localeCompare(labelB));
|
||||
})
|
||||
|
||||
const entryMap = new Map<string, boolean>();
|
||||
|
@ -22,7 +22,9 @@
|
||||
package com.kingsrook.qqq.frontend.materialdashboard.model.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.layout.QSupplementalAppMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -30,7 +32,39 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QSupplementalAppMeta
|
||||
*******************************************************************************/
|
||||
public class MaterialDashboardAppMetaData extends QSupplementalAppMetaData
|
||||
{
|
||||
public static final String TYPE_NAME = "materialDashboard";
|
||||
|
||||
private Boolean showAppLabelOnHomeScreen = true;
|
||||
private Boolean includeTableCountsOnHomeScreen = true;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static MaterialDashboardAppMetaData of(QAppMetaData app)
|
||||
{
|
||||
return ((MaterialDashboardAppMetaData) CollectionUtils.nonNullMap(app.getSupplementalMetaData()).get(TYPE_NAME));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** either get the supplemental meta dat attached to an app - or create a new one
|
||||
** and attach it to the app, and return that.
|
||||
*******************************************************************************/
|
||||
public static MaterialDashboardAppMetaData ofOrWithNew(QAppMetaData app)
|
||||
{
|
||||
MaterialDashboardAppMetaData materialDashboardAppMetaData = of(app);
|
||||
|
||||
if(materialDashboardAppMetaData == null)
|
||||
{
|
||||
materialDashboardAppMetaData = new MaterialDashboardAppMetaData();
|
||||
app.withSupplementalMetaData(materialDashboardAppMetaData);
|
||||
}
|
||||
|
||||
return (materialDashboardAppMetaData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -51,7 +85,7 @@ public class MaterialDashboardAppMetaData extends QSupplementalAppMetaData
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return ("materialDashboard");
|
||||
return TYPE_NAME;
|
||||
}
|
||||
|
||||
|
||||
@ -85,4 +119,35 @@ public class MaterialDashboardAppMetaData extends QSupplementalAppMetaData
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for includeTableCountsOnHomeScreen
|
||||
*******************************************************************************/
|
||||
public Boolean getIncludeTableCountsOnHomeScreen()
|
||||
{
|
||||
return (this.includeTableCountsOnHomeScreen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for includeTableCountsOnHomeScreen
|
||||
*******************************************************************************/
|
||||
public void setIncludeTableCountsOnHomeScreen(Boolean includeTableCountsOnHomeScreen)
|
||||
{
|
||||
this.includeTableCountsOnHomeScreen = includeTableCountsOnHomeScreen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for includeTableCountsOnHomeScreen
|
||||
*******************************************************************************/
|
||||
public MaterialDashboardAppMetaData withIncludeTableCountsOnHomeScreen(Boolean includeTableCountsOnHomeScreen)
|
||||
{
|
||||
this.includeTableCountsOnHomeScreen = includeTableCountsOnHomeScreen;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ export default function ExportMenuItem(props: QExportMenuItemProps)
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
disabled={!totalRecords}
|
||||
disabled={totalRecords === 0}
|
||||
onClick={() =>
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -94,6 +94,24 @@ export const makeTextField = (field: QFieldMetaData, criteria: QFilterCriteriaWi
|
||||
document.getElementById(`${idPrefix}${criteria.id}`).focus();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Event handler for key-down events - specifically added here, to stop pressing
|
||||
** 'tab' in a date or date-time from closing the quick-filter...
|
||||
*******************************************************************************/
|
||||
const handleKeyDown = (e: any) =>
|
||||
{
|
||||
if (field.type == QFieldType.DATE || field.type == QFieldType.DATE_TIME)
|
||||
{
|
||||
if(e.code == "Tab")
|
||||
{
|
||||
console.log("Tab on date or date-time - don't close me, just move to the next sub-field!...");
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const inputProps: any = {};
|
||||
inputProps.endAdornment = (
|
||||
<InputAdornment position="end">
|
||||
@ -110,6 +128,7 @@ export const makeTextField = (field: QFieldMetaData, criteria: QFilterCriteriaWi
|
||||
autoComplete="off"
|
||||
type={type}
|
||||
onChange={(event) => valueChangeHandler(event, valueIndex)}
|
||||
onKeyDown={handleKeyDown}
|
||||
value={value}
|
||||
InputLabelProps={inputLabelProps}
|
||||
InputProps={inputProps}
|
||||
|
@ -504,7 +504,7 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData
|
||||
//////////////////////////////
|
||||
// return the button & menu //
|
||||
//////////////////////////////
|
||||
const widthAndMaxWidth = 250
|
||||
const widthAndMaxWidth = fieldMetaData?.type == QFieldType.DATE_TIME ? 275 : 250
|
||||
return (
|
||||
<>
|
||||
{button}
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
import BlockElementWrapper from "qqq/components/widgets/blocks/BlockElementWrapper";
|
||||
import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockModels";
|
||||
import UpOrDownNumberBlock from "qqq/components/widgets/blocks/UpOrDownNumberBlock";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -40,7 +38,7 @@ export default function BigNumberBlock({widgetMetaData, data}: StandardBlockComp
|
||||
<div style={{width: data.styles.width ?? "auto"}}>
|
||||
|
||||
<div style={{fontWeight: "700", fontSize: "0.875rem", color: "#3D3D3D", marginBottom: "-0.5rem"}}>
|
||||
<BlockElementWrapper data={data} slot="heading">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="heading">
|
||||
<span>{data.values.heading}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
@ -49,14 +47,14 @@ export default function BigNumberBlock({widgetMetaData, data}: StandardBlockComp
|
||||
|
||||
<div style={{display: "flex", alignItems: "baseline"}}>
|
||||
<div style={{fontWeight: "700", fontSize: "2rem", marginRight: "0.25rem"}}>
|
||||
<BlockElementWrapper data={data} slot="number">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="number">
|
||||
<span style={{color: data.styles.numberColor}}>{data.values.number}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
{
|
||||
data.values.context &&
|
||||
<div style={{fontWeight: "500", fontSize: "0.875rem", color: "#7b809a"}}>
|
||||
<BlockElementWrapper data={data} slot="context">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="context">
|
||||
<span>{data.values.context}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
|
@ -20,14 +20,18 @@
|
||||
*/
|
||||
|
||||
|
||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||
import {Tooltip} from "@mui/material";
|
||||
import React, {ReactElement} from "react";
|
||||
import React, {ReactElement, useContext} from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import QContext from "QContext";
|
||||
import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent";
|
||||
import {BlockData, BlockLink, BlockTooltip} from "qqq/components/widgets/blocks/BlockModels";
|
||||
|
||||
interface BlockElementWrapperProps
|
||||
{
|
||||
data: BlockData;
|
||||
metaData: QWidgetMetaData;
|
||||
slot: string
|
||||
linkProps?: any;
|
||||
children: ReactElement;
|
||||
@ -36,8 +40,10 @@ interface BlockElementWrapperProps
|
||||
/*******************************************************************************
|
||||
** For Blocks - wrap their "slot" elements with an optional tooltip and/or link
|
||||
*******************************************************************************/
|
||||
export default function BlockElementWrapper({data, slot, linkProps, children}: BlockElementWrapperProps): JSX.Element
|
||||
export default function BlockElementWrapper({data, metaData, slot, linkProps, children}: BlockElementWrapperProps): JSX.Element
|
||||
{
|
||||
const {helpHelpActive} = useContext(QContext);
|
||||
|
||||
let link: BlockLink;
|
||||
let tooltip: BlockTooltip;
|
||||
|
||||
@ -61,6 +67,26 @@ export default function BlockElementWrapper({data, slot, linkProps, children}: B
|
||||
tooltip = data.tooltip;
|
||||
}
|
||||
|
||||
if(!tooltip)
|
||||
{
|
||||
const helpRoles = ["ALL_SCREENS"]
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// the full keys in the helpContent table will look like: //
|
||||
// widget:MyCoolWidget;slot=myBlockId,label (if the block has a blockId in data) //
|
||||
// widget:MyCoolWidget;slot=label (no blockId; note, label is slot name here) //
|
||||
// in the widget metaData, the map of helpContent will just have the "slot" portion as a key //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const key = data.blockId ? `${data.blockId},${slot}` : slot;
|
||||
const showHelp = helpHelpActive || hasHelpContent(metaData?.helpContent?.get(key), helpRoles);
|
||||
|
||||
if(showHelp)
|
||||
{
|
||||
const formattedHelpContent = <HelpContent helpContents={metaData?.helpContent?.get(key)} roles={helpRoles} helpContentKey={`widget:${metaData?.name};slot:${key}`} />;
|
||||
tooltip = {title: formattedHelpContent, placement: "bottom"}
|
||||
}
|
||||
}
|
||||
|
||||
let rs = children;
|
||||
|
||||
if(link)
|
||||
|
@ -24,6 +24,7 @@ import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Q
|
||||
|
||||
export interface BlockData
|
||||
{
|
||||
blockId?: string;
|
||||
blockTypeName: string;
|
||||
|
||||
tooltip?: BlockTooltip;
|
||||
@ -38,7 +39,7 @@ export interface BlockData
|
||||
|
||||
export interface BlockTooltip
|
||||
{
|
||||
title: string;
|
||||
title: string | JSX.Element;
|
||||
placement: string;
|
||||
}
|
||||
|
||||
|
@ -28,19 +28,19 @@ import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockMo
|
||||
**
|
||||
** ${number} ${icon}
|
||||
*******************************************************************************/
|
||||
export default function NumberIconBadgeBlock({data}: StandardBlockComponentProps): JSX.Element
|
||||
export default function NumberIconBadgeBlock({widgetMetaData, data}: StandardBlockComponentProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<div style={{display: "inline-block", whiteSpace: "nowrap", color: data.styles.color}}>
|
||||
{
|
||||
data.values.number &&
|
||||
<BlockElementWrapper data={data} slot="number">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="number">
|
||||
<span style={{color: data.styles.color, fontSize: "0.875rem"}}>{data.values.number}</span>
|
||||
</BlockElementWrapper>
|
||||
}
|
||||
{
|
||||
data.values.iconName &&
|
||||
<BlockElementWrapper data={data} slot="icon">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="icon">
|
||||
<Icon style={{color: data.styles.color, fontSize: "1rem", position: "relative", top: "3px"}}>{data.values.iconName}</Icon>
|
||||
</BlockElementWrapper>
|
||||
}
|
||||
|
@ -35,14 +35,14 @@ import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockMo
|
||||
** ${heading}
|
||||
** ${bar} ${value}
|
||||
*******************************************************************************/
|
||||
export default function ProgressBarBlock({data}: StandardBlockComponentProps): JSX.Element
|
||||
export default function ProgressBarBlock({widgetMetaData, data}: StandardBlockComponentProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<Typography component="div" variant="button" color="text" fontWeight="light" sx={{textTransform: "none"}}>
|
||||
{
|
||||
data.values.heading &&
|
||||
<div style={{marginBottom: "0.25rem", fontWeight: 500, color: "#3D3D3D"}}>
|
||||
<BlockElementWrapper data={data} slot="heading">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="heading">
|
||||
<span>{data.values.heading}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
@ -50,7 +50,7 @@ export default function ProgressBarBlock({data}: StandardBlockComponentProps): J
|
||||
|
||||
<div style={{display: "flex", alignItems: "center", marginBottom: "0.75rem"}}>
|
||||
|
||||
<BlockElementWrapper data={data} slot="bar" linkProps={{style: {width: "100%"}}}>
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="bar" linkProps={{style: {width: "100%"}}}>
|
||||
<div style={{background: "#E0E0E0", width: "100%", borderRadius: "0.5rem", height: "1rem"}}>
|
||||
{
|
||||
data.values.percent > 0 ? <div style={{background: data.styles.barColor ?? "#0062ff", minWidth: "1rem", width: `${data.values.percent}%`, borderRadius: "0.5rem", height: "1rem"}}></div> : <></>
|
||||
@ -59,7 +59,7 @@ export default function ProgressBarBlock({data}: StandardBlockComponentProps): J
|
||||
</BlockElementWrapper>
|
||||
|
||||
<div style={{width: "60px", textAlign: "right", fontWeight: 600, color: "#3D3D3D"}}>
|
||||
<BlockElementWrapper data={data} slot="value">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="value">
|
||||
<span>{data.values.value ?? `${(data.values.percent as number).toFixed(1)}%`}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
|
@ -29,7 +29,7 @@ import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockMo
|
||||
**
|
||||
** ${label} ${value}
|
||||
*******************************************************************************/
|
||||
export default function TableSubRowDetailRowBlock({data}: StandardBlockComponentProps): JSX.Element
|
||||
export default function TableSubRowDetailRowBlock({widgetMetaData, data}: StandardBlockComponentProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<div style={{display: "flex", maxWidth: "calc(100% - 24px)", justifyContent: "space-between"}}>
|
||||
@ -37,7 +37,7 @@ export default function TableSubRowDetailRowBlock({data}: StandardBlockComponent
|
||||
{
|
||||
data.values.label &&
|
||||
<div style={{overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis"}}>
|
||||
<BlockElementWrapper data={data} slot="label">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="label">
|
||||
<span style={{color: data.styles.labelColor}}>{data.values.label}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
@ -45,7 +45,7 @@ export default function TableSubRowDetailRowBlock({data}: StandardBlockComponent
|
||||
|
||||
{
|
||||
data.values.value &&
|
||||
<BlockElementWrapper data={data} slot="value">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="value">
|
||||
<span style={{color: data.styles.valueColor}}>{data.values.value}</span>
|
||||
</BlockElementWrapper>
|
||||
}
|
||||
|
@ -27,10 +27,10 @@ import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockMo
|
||||
**
|
||||
** ${text}
|
||||
*******************************************************************************/
|
||||
export default function TextBlock({data}: StandardBlockComponentProps): JSX.Element
|
||||
export default function TextBlock({widgetMetaData, data}: StandardBlockComponentProps): JSX.Element
|
||||
{
|
||||
return (
|
||||
<BlockElementWrapper data={data} slot="">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="">
|
||||
<span>{data.values.text}</span>
|
||||
</BlockElementWrapper>
|
||||
);
|
||||
|
@ -35,7 +35,7 @@ import {StandardBlockComponentProps} from "qqq/components/widgets/blocks/BlockMo
|
||||
** ${icon} ${number}
|
||||
** ${context}
|
||||
*******************************************************************************/
|
||||
export default function UpOrDownNumberBlock({data}: StandardBlockComponentProps): JSX.Element
|
||||
export default function UpOrDownNumberBlock({widgetMetaData, data}: StandardBlockComponentProps): JSX.Element
|
||||
{
|
||||
if (!data.styles)
|
||||
{
|
||||
@ -61,7 +61,7 @@ export default function UpOrDownNumberBlock({data}: StandardBlockComponentProps)
|
||||
<div style={{display: "flex", flexDirection: data.styles.isStacked ? "column" : "row", alignItems: data.styles.isStacked ? "flex-end" : "baseline"}}>
|
||||
|
||||
<div style={{display: "flex", alignItems: "baseline", fontWeight: 700, fontSize: ".875rem"}}>
|
||||
<BlockElementWrapper data={data} slot="number">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="number">
|
||||
<>
|
||||
<Icon sx={{color: goodOrBadColor, alignSelf: "flex-end", fontSize: "2.25rem !important", lineHeight: "0.875rem", height: "1rem", width: "2rem",}}>{iconName}</Icon>
|
||||
<span style={{color: goodOrBadColor}}>{data.values.number}</span>
|
||||
@ -70,7 +70,7 @@ export default function UpOrDownNumberBlock({data}: StandardBlockComponentProps)
|
||||
</div>
|
||||
|
||||
<div style={{fontWeight: 500, fontSize: "0.875rem", color: "#7b809a", marginLeft: "0.25rem"}}>
|
||||
<BlockElementWrapper data={data} slot="context">
|
||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="context">
|
||||
<span>{data.values.context}</span>
|
||||
</BlockElementWrapper>
|
||||
</div>
|
||||
|
@ -77,9 +77,11 @@ function AppHome({app}: Props): JSX.Element
|
||||
|
||||
const mdbMetaData = app?.supplementalAppMetaData?.get("materialDashboard");
|
||||
let showAppLabelOnHomeScreen = true;
|
||||
let includeTableCountsOnHomeScreen = true;
|
||||
if(mdbMetaData)
|
||||
{
|
||||
showAppLabelOnHomeScreen = mdbMetaData.showAppLabelOnHomeScreen;
|
||||
includeTableCountsOnHomeScreen = mdbMetaData.includeTableCountsOnHomeScreen;
|
||||
}
|
||||
|
||||
useEffect(() =>
|
||||
@ -129,48 +131,60 @@ function AppHome({app}: Props): JSX.Element
|
||||
const tableCountTexts = new Map<string, string>();
|
||||
newTables.forEach((table) =>
|
||||
{
|
||||
tableCounts.set(table.name, {isLoading: true, value: null});
|
||||
|
||||
setTimeout(async () =>
|
||||
if(includeTableCountsOnHomeScreen)
|
||||
{
|
||||
const tableMetaData = await qController.loadTableMetaData(table.name);
|
||||
let countResult = null;
|
||||
if(tableMetaData.capabilities.has(Capability.TABLE_COUNT) && tableMetaData.readPermission)
|
||||
tableCounts.set(table.name, {isLoading: true, value: null});
|
||||
setTimeout(async () =>
|
||||
{
|
||||
try
|
||||
const tableMetaData = await qController.loadTableMetaData(table.name);
|
||||
let countResult = null;
|
||||
if (tableMetaData.capabilities.has(Capability.TABLE_COUNT) && tableMetaData.readPermission)
|
||||
{
|
||||
[countResult] = await qController.count(table.name);
|
||||
try
|
||||
{
|
||||
[countResult] = await qController.count(table.name);
|
||||
|
||||
if (countResult !== null && countResult !== undefined)
|
||||
{
|
||||
tableCountNumbers.set(table.name, countResult.toLocaleString());
|
||||
tableCountTexts.set(table.name, countResult === 1 ? "total record" : "total records");
|
||||
if (countResult !== null && countResult !== undefined)
|
||||
{
|
||||
tableCountNumbers.set(table.name, countResult.toLocaleString());
|
||||
tableCountTexts.set(table.name, countResult === 1 ? "total record" : "total records");
|
||||
}
|
||||
else
|
||||
{
|
||||
tableCountNumbers.set(table.name, "–");
|
||||
tableCountTexts.set(table.name, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (e)
|
||||
{
|
||||
console.log("Caught: " + e);
|
||||
tableCountNumbers.set(table.name, "–");
|
||||
tableCountTexts.set(table.name, " ");
|
||||
}
|
||||
}
|
||||
catch(e)
|
||||
else
|
||||
{
|
||||
console.log("Caught: " + e);
|
||||
tableCountNumbers.set(table.name, "–");
|
||||
tableCountTexts.set(table.name, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tableCountNumbers.set(table.name, "–");
|
||||
tableCountTexts.set(table.name, " ");
|
||||
}
|
||||
|
||||
tableCounts.set(table.name, {isLoading: false, value: countResult});
|
||||
tableCounts.set(table.name, {isLoading: false, value: countResult});
|
||||
setTableCounts(tableCounts);
|
||||
setTableCountNumbers(tableCountNumbers);
|
||||
setTableCountTexts(tableCountTexts);
|
||||
setUpdatedTableCounts(new Date());
|
||||
}, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
tableCounts.set(table.name, {isLoading: false, value: null});
|
||||
tableCountNumbers.set(table.name, " ");
|
||||
tableCountTexts.set(table.name, " ");
|
||||
|
||||
setTableCounts(tableCounts);
|
||||
setTableCountNumbers(tableCountNumbers);
|
||||
setTableCountTexts(tableCountTexts);
|
||||
setUpdatedTableCounts(new Date());
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
setTableCounts(tableCounts);
|
||||
|
||||
@ -299,7 +313,7 @@ function AppHome({app}: Props): JSX.Element
|
||||
</Box>
|
||||
{
|
||||
section.processes ? (
|
||||
<Box p={3} pl={5} pt={0} pb={1}>
|
||||
<Box p={3} pl={3} pt={0} pb={1}>
|
||||
<MDTypography variant="h6">Actions</MDTypography>
|
||||
</Box>
|
||||
) : null
|
||||
@ -340,7 +354,7 @@ function AppHome({app}: Props): JSX.Element
|
||||
}
|
||||
{
|
||||
section.reports ? (
|
||||
<Box p={3} pl={5} pt={0} pb={1}>
|
||||
<Box p={3} pl={3} pt={0} pb={1}>
|
||||
<MDTypography variant="h6">Reports</MDTypography>
|
||||
</Box>
|
||||
) : null
|
||||
@ -383,7 +397,7 @@ function AppHome({app}: Props): JSX.Element
|
||||
}
|
||||
{
|
||||
section.tables ? (
|
||||
<Box p={3} pl={5} pb={1} pt={0}>
|
||||
<Box p={3} pl={3} pb={1} pt={0}>
|
||||
<MDTypography variant="h6">Data</MDTypography>
|
||||
</Box>
|
||||
) : null
|
||||
@ -395,6 +409,13 @@ function AppHome({app}: Props): JSX.Element
|
||||
section.tables.map((tableName) =>
|
||||
{
|
||||
let table = app.childMap.get(tableName);
|
||||
let count = "";
|
||||
let percentage = "";
|
||||
if(includeTableCountsOnHomeScreen)
|
||||
{
|
||||
count = !tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "..." : (tableCountNumbers.get(table.name));
|
||||
percentage = !tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "" : (tableCountTexts.get(table.name));
|
||||
}
|
||||
return (
|
||||
<Grid key={table.name} item xs={12} md={12} lg={tileSizeLg}>
|
||||
{hasTablePermission(tableName) ?
|
||||
@ -402,8 +423,8 @@ function AppHome({app}: Props): JSX.Element
|
||||
<Box className="big-icon" mb={3}>
|
||||
<MiniStatisticsCard
|
||||
title={{fontWeight: "bold", text: table.label}}
|
||||
count={!tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "..." : (tableCountNumbers.get(table.name))}
|
||||
percentage={{color: "info", text: (!tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "" : (tableCountTexts.get(table.name)))}}
|
||||
count={count}
|
||||
percentage={{color: "info", text: percentage}}
|
||||
icon={{color: "info", component: <Icon>{table.iconName || app.iconName}</Icon>}}
|
||||
/>
|
||||
</Box>
|
||||
@ -411,8 +432,8 @@ function AppHome({app}: Props): JSX.Element
|
||||
<Box mb={3} title="You do not have permission to access this table">
|
||||
<MiniStatisticsCard
|
||||
title={{fontWeight: "bold", text: table.label}}
|
||||
count={!tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "..." : (tableCountNumbers.get(table.name))}
|
||||
percentage={{color: "info", text: (!tableCounts.has(table.name) || tableCounts.get(table.name).isLoading ? "" : (tableCountTexts.get(table.name)))}}
|
||||
count={count}
|
||||
percentage={{color: "info", text: percentage}}
|
||||
icon={{color: "info", component: <Icon>{table.iconName || app.iconName}</Icon>}}
|
||||
isDisabled={true}
|
||||
/>
|
||||
|
@ -114,8 +114,11 @@ class FilterUtils
|
||||
// e.g., ...values=[1]... //
|
||||
// but we need them to be possibleValue objects (w/ id & label) so the label //
|
||||
// can be shown in the filter dropdown. So, make backend call to look them up. //
|
||||
// also, there are cases where we can get a null or "" as the only value in the //
|
||||
// values array - avoid sending that to the backend, as it comes back w/ all //
|
||||
// possible values, and a general "bad time" //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
if (values && values.length > 0)
|
||||
if (values && values.length > 0 && values[0] !== null && values[0] !== undefined && values[0] !== "")
|
||||
{
|
||||
values = await qController.possibleValues(fieldTable.name, null, field.name, "", values);
|
||||
}
|
||||
|
Reference in New Issue
Block a user