SPRINT-19: upped core frontend version, updates to pie charts and stacked charts

This commit is contained in:
Tim Chamberlain
2023-01-25 19:12:43 -06:00
parent 895724b87e
commit 4ac1063bca
10 changed files with 107 additions and 85 deletions

26
package-lock.json generated
View File

@ -11,7 +11,7 @@
"@auth0/auth0-react": "1.10.2",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
"@kingsrook/qqq-frontend-core": "1.0.45",
"@kingsrook/qqq-frontend-core": "1.0.48",
"@mui/icons-material": "5.4.1",
"@mui/material": "5.11.1",
"@mui/styles": "5.11.1",
@ -3354,9 +3354,9 @@
}
},
"node_modules/@kingsrook/qqq-frontend-core": {
"version": "1.0.45",
"resolved": "https://npm.pkg.github.com/download/@Kingsrook/qqq-frontend-core/1.0.45/adee99b089456ae72ee9a311d35f6def5d308486",
"integrity": "sha512-eT/Kp+Y69926DLVTvaRwyeGHPjWYuYOCR2CqwUf4UMrbtZC4tHsrI8uKisZ/ulZeNxm/6N/m0A+ElrXAnt5+mA==",
"version": "1.0.48",
"resolved": "https://npm.pkg.github.com/download/@Kingsrook/qqq-frontend-core/1.0.48/27c1a09d17eccc82cf07c76db8c74ee89a92161e",
"integrity": "sha512-781sx4RxIh6x5azNh+Nh5wtP5dPZ8nprTYVPNrBH0XsPB397bxgF3+bjfdtDFpaBkRAWuCiKoVEcz5eJZtT9dg==",
"license": "ISC",
"dependencies": {
"axios": "0.27.2",
@ -6529,9 +6529,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001447",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw==",
"version": "1.0.30001448",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001448.tgz",
"integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==",
"funding": [
{
"type": "opencollective",
@ -23098,9 +23098,9 @@
}
},
"@kingsrook/qqq-frontend-core": {
"version": "1.0.45",
"resolved": "https://npm.pkg.github.com/download/@Kingsrook/qqq-frontend-core/1.0.45/adee99b089456ae72ee9a311d35f6def5d308486",
"integrity": "sha512-eT/Kp+Y69926DLVTvaRwyeGHPjWYuYOCR2CqwUf4UMrbtZC4tHsrI8uKisZ/ulZeNxm/6N/m0A+ElrXAnt5+mA==",
"version": "1.0.48",
"resolved": "https://npm.pkg.github.com/download/@Kingsrook/qqq-frontend-core/1.0.48/27c1a09d17eccc82cf07c76db8c74ee89a92161e",
"integrity": "sha512-781sx4RxIh6x5azNh+Nh5wtP5dPZ8nprTYVPNrBH0XsPB397bxgF3+bjfdtDFpaBkRAWuCiKoVEcz5eJZtT9dg==",
"requires": {
"axios": "0.27.2",
"form-data": "4.0.0"
@ -25390,9 +25390,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001447",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw=="
"version": "1.0.30001448",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001448.tgz",
"integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA=="
},
"case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",

View File

@ -7,7 +7,7 @@
"@auth0/auth0-react": "1.10.2",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
"@kingsrook/qqq-frontend-core": "1.0.45",
"@kingsrook/qqq-frontend-core": "1.0.48",
"@mui/icons-material": "5.4.1",
"@mui/material": "5.11.1",
"@mui/styles": "5.11.1",

View File

@ -47,7 +47,7 @@ import MultiStatisticsCard from "qqq/components/widgets/statistics/MultiStatisti
import SimpleStatisticsCard from "qqq/components/widgets/statistics/SimpleStatisticsCard";
import StatisticsCard from "qqq/components/widgets/statistics/StatisticsCard";
import TableCard from "qqq/components/widgets/tables/TableCard";
import Widget from "qqq/components/widgets/Widget";
import Widget, {WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT} from "qqq/components/widgets/Widget";
import ProcessRun from "qqq/pages/processes/ProcessRun";
import Client from "qqq/utils/qqq/Client";
@ -81,6 +81,9 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
const [widgetCounter, setWidgetCounter] = useState(0);
const [, forceUpdate] = useReducer((x) => x + 1, 0);
const [currentUrlParams, setCurrentUrlParams] = useState(null as string);
const [haveLoadedParams, setHaveLoadedParams] = useState(false);
useEffect(() =>
{
(async () =>
@ -92,24 +95,23 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
useEffect(() =>
{
if (!qInstance)
{
return;
}
forceUpdate();
for (let i = 0; i < widgetMetaDataList.length; i++)
{
const widgetMetaData = widgetMetaDataList[i];
const urlParams = getQueryParams(widgetMetaData, null);
setCurrentUrlParams(urlParams);
setHaveLoadedParams(true);
widgetData[i] = {};
(async () =>
{
widgetData[i] = await qController.widget(widgetMetaDataList[i].name, getQueryParams(null));
widgetData[i] = await qController.widget(widgetMetaData.name, urlParams);
setWidgetCounter(widgetCounter + 1);
forceUpdate();
})();
}
setWidgetData(widgetData);
}, [qInstance, widgetMetaDataList]);
}, [widgetMetaDataList]);
useEffect(() =>
{
@ -120,16 +122,15 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
{
setTimeout(async () =>
{
widgetData[index] = await qController.widget(widgetMetaDataList[index].name, getQueryParams(data));
widgetData[index] = await qController.widget(widgetMetaDataList[index].name, getQueryParams(null, data));
setWidgetCounter(widgetCounter + 1);
}, 1);
};
function getQueryParams(extraParams: string): string
function getQueryParams(widgetMetaData: QWidgetMetaData, extraParams: string): string
{
let ampersand = "";
let params = "";
let foundParam = false;
if(entityPrimaryKey)
{
params += `${ampersand}id=${entityPrimaryKey}`;
@ -148,6 +149,26 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
if(childUrlParams)
{
params += `${ampersand}${childUrlParams}`;
ampersand = "&";
}
/////////////////////////////////////////////////////////////////////////////
// see if local storage is used for any widget dropdowns, if so, look them //
// up and append to the query string //
/////////////////////////////////////////////////////////////////////////////
if(widgetMetaData && widgetMetaData.storeDropdownSelections && widgetMetaData.dropdowns)
{
for(let i = 0; i< widgetMetaData.dropdowns.length; i++)
{
const dropdownName = widgetMetaData.dropdowns[i].possibleValueSourceName;
const localStorageKey = `${WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT}.${widgetMetaData.name}.${dropdownName}`;
const json = JSON.parse(localStorage.getItem(localStorageKey));
if(json)
{
params += `${ampersand}${dropdownName}=${json.id}`;
ampersand = "&";
}
}
}
return params;
@ -160,8 +181,9 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
return (
<Box key={`${widgetMetaData.name}-${i}`} sx={{alignItems: "stretch", flexGrow: 1, display: "flex", marginTop: "0px", paddingTop: "0px", width: "100%", height: "100%"}}>
{
widgetMetaData.type === "parentWidget" && (
haveLoadedParams && widgetMetaData.type === "parentWidget" && (
<ParentWidget
urlParams={currentUrlParams}
entityPrimaryKey={entityPrimaryKey}
tableName={tableName}
widgetIndex={i}

View File

@ -50,6 +50,7 @@ export interface ParentWidgetData
////////////////////////////////////
interface Props
{
urlParams?: string;
widgetMetaData?: QWidgetMetaData;
widgetIndex: number;
data: ParentWidgetData;
@ -61,9 +62,9 @@ interface Props
const qController = Client.getInstance();
function ParentWidget({widgetMetaData, widgetIndex, data, reloadWidgetCallback, entityPrimaryKey, tableName, storeDropdownSelections}: Props, ): JSX.Element
function ParentWidget({urlParams, widgetMetaData, widgetIndex, data, reloadWidgetCallback, entityPrimaryKey, tableName, storeDropdownSelections}: Props, ): JSX.Element
{
const [childUrlParams, setChildUrlParams] = useState("");
const [childUrlParams, setChildUrlParams] = useState((urlParams) ? urlParams : "");
const [qInstance, setQInstance] = useState(null as QInstance);
const [widgets, setWidgets] = useState([] as any[]);
@ -87,7 +88,7 @@ function ParentWidget({widgetMetaData, widgetIndex, data, reloadWidgetCallback,
})
setWidgets(widgetMetaDataList);
}
}, [qInstance, data]);
}, [qInstance, data, childUrlParams]);
const parentReloadWidgetCallback = (data: string) =>
{
@ -98,6 +99,7 @@ function ParentWidget({widgetMetaData, widgetIndex, data, reloadWidgetCallback,
// @ts-ignore
return (
qInstance && data ? (
<Widget
widgetMetaData={widgetMetaData}
widgetData={data}
@ -108,6 +110,7 @@ function ParentWidget({widgetMetaData, widgetIndex, data, reloadWidgetCallback,
<DashboardWidgets widgetMetaDataList={widgets} entityPrimaryKey={entityPrimaryKey} tableName={tableName} childUrlParams={childUrlParams} areChildren={true} />
</Box>
</Widget>
) : null
);
}

View File

@ -33,6 +33,7 @@ import DropdownMenu, {DropdownOption} from "qqq/components/widgets/components/Dr
export interface WidgetData
{
label?: string;
dropdownLabelList?: string[];
dropdownNameList?: string[];
dropdownDataList?: {
@ -120,7 +121,7 @@ export class Dropdown extends LabelComponent
}
const WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT = "qqq.widgets.dropdownData";
export const WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT = "qqq.widgets.dropdownData";
function Widget(props: React.PropsWithChildren<Props>): JSX.Element
@ -254,7 +255,7 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
useEffect(() =>
{
if(dropdownData)
if(dropdownData && counter > 0)
{
let params = "";
for (let i = 0; i < dropdownData.length; i++)
@ -311,11 +312,20 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
)
}
{
//////////////////////////////////////////////////////////////////////////////////////////
// first look for a label in the widget data, which would override that in the metadata //
//////////////////////////////////////////////////////////////////////////////////////////
props.widgetData?.label? (
<Typography variant="h5" fontWeight="medium" pl={3} display="inline">
{props.widgetData.label}
</Typography>
) : (
props.widgetMetaData?.label && (
<Typography variant="h5" fontWeight="medium" pl={3} display="inline">
{props.widgetMetaData.label}
</Typography>
)
)
}
{
props.labelAdditionalComponentsLeft.map((component, i) =>

View File

@ -28,6 +28,7 @@ export const chartColors = ["info", "warning", "primary", "success", "error", "s
export interface DefaultChartData
{
labels: string[];
urls?: string[];
datasets: [
{
label: string;

View File

@ -22,8 +22,9 @@
import Box from "@mui/material/Box";
import {BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip,} from "chart.js";
import React from "react";
import React, {useEffect} from "react";
import {Bar} from "react-chartjs-2";
import {useNavigate} from "react-router-dom";
import colors from "qqq/assets/theme/base/colors";
import {chartColors, DefaultChartData} from "qqq/components/widgets/charts/DefaultChartData";
@ -56,20 +57,22 @@ interface Props
const {gradients} = colors;
function StackedBarChart({data}: Props): JSX.Element
{
const navigate = useNavigate();
const handleClick = (e: Array<{}>) =>
{
/*
if(e && e.length > 0 && data?.dataset?.urls && data?.dataset?.urls.length)
if(e && e.length > 0 && data?.urls && data?.urls.length)
{
// @ts-ignore
navigate(chartData.dataset.urls[e[0]["index"]]);
navigate(data.urls[e[0]["index"]]);
}
*/
console.log(e);
}
useEffect(() =>
{
if(data)
{
data?.datasets.forEach((dataset: any, index: number) =>
{
if (!dataset.backgroundColor)
@ -77,8 +80,13 @@ function StackedBarChart({data}: Props): JSX.Element
dataset.backgroundColor = gradients[chartColors[index]].state;
}
});
}
}, [data]);
return <Box p={3}><Bar data={data} options={options} getElementsAtEvent={handleClick} /></Box>;
return data ? (
<Box p={3}><Bar data={data} options={options} getElementsAtEvent={handleClick} /></Box>
) : null;
}
export default StackedBarChart;

View File

@ -27,7 +27,6 @@ import parse from "html-react-parser";
import React, {useMemo} from "react";
import {Pie} from "react-chartjs-2";
import {useNavigate} from "react-router-dom";
import MDBadgeDot from "qqq/components/legacy/MDBadgeDot";
import MDTypography from "qqq/components/legacy/MDTypography";
import {chartColors} from "qqq/components/widgets/charts/DefaultChartData";
import configs from "qqq/components/widgets/charts/piechart/PieChartConfigs";
@ -56,6 +55,7 @@ interface Props
[key: string]: any;
}
function PieChart({description, chartData}: Props): JSX.Element
{
const navigate = useNavigate();
@ -80,9 +80,8 @@ function PieChart({description, chartData}: Props): JSX.Element
<Card sx={{boxShadow: "none", height: "100%", width: "100%", display: "flex", flexGrow: 1}}>
<Box mt={3}>
<Grid container alignItems="center">
<Grid item xs={5}>
<Box py={2} pr={2} pl={2}>
<Grid item xs={12} justifyContent="center">
<Box width="100%" height="80%" py={2} pr={2} pl={2}>
{useMemo(
() => (
<Pie data={data} options={options} getElementsAtEvent={handleClick} />
@ -91,19 +90,6 @@ function PieChart({description, chartData}: Props): JSX.Element
)}
</Box>
</Grid>
<Grid item xs={7}>
<Box pr={1}>
{
data && data.labels ? (
(data.labels.map((label: string, index: number) => (
<Box key={index}>
<MDBadgeDot color={chartColors[index]} size="sm" badgeContent={label} />
</Box>
)
))) : null
}
</Box>
</Grid>
</Grid>
<Divider />
{

View File

@ -58,11 +58,12 @@ function configs(labels: any, datasets: any)
],
},
options: {
responsive: true,
maintainAspectRatio: true,
responsive: true,
aspectRatio: 2,
plugins: {
legend: {
display: false,
position: "bottom",
},
},
scales: {

View File

@ -23,7 +23,7 @@ import {Theme} from "@mui/material";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
import {SxProps} from "@mui/system";
import React, {useEffect} from "react";
import React from "react";
export interface DropdownOption
@ -47,15 +47,6 @@ interface Props
function DropdownMenu({localStorageKey, defaultValue, label, dropdownOptions, onChangeCallback, sx}: Props): JSX.Element
{
useEffect(() =>
{
if(defaultValue)
{
console.log("CALLING CALLBACK...")
onChangeCallback(label, JSON.parse(localStorage.getItem(localStorageKey)));
}
}, []);
const handleOnChange = (event: any, value: any, reason: string) =>
{
onChangeCallback(label, value);