From 0057fdf3ea4fbd5a9357047074845ef3b6e30968 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Wed, 7 Dec 2022 15:27:50 -0600 Subject: [PATCH] SPRINT-17: checkpoint commit of freight study optimization dashboard widgets --- src/qqq/components/DashboardWidgets.tsx | 46 ++++++++-- .../Configs/HorizontalBarChartConfigs.ts | 87 ------------------- .../dashboards/Widgets/DefaultLineChart.tsx | 52 ++++++++++- .../dashboards/Widgets/HorizontalBarChart.tsx | 54 ++++++++++-- .../pages/dashboards/Widgets/ParentWidget.tsx | 9 +- .../Widgets/SimpleStatisticsCard.tsx | 28 +++--- 6 files changed, 155 insertions(+), 121 deletions(-) delete mode 100644 src/qqq/pages/dashboards/Widgets/Configs/HorizontalBarChartConfigs.ts diff --git a/src/qqq/components/DashboardWidgets.tsx b/src/qqq/components/DashboardWidgets.tsx index c4a81a5..34a4954 100644 --- a/src/qqq/components/DashboardWidgets.tsx +++ b/src/qqq/components/DashboardWidgets.tsx @@ -31,17 +31,20 @@ import MDBadgeDot from "qqq/components/Temporary/MDBadgeDot"; import MDBox from "qqq/components/Temporary/MDBox"; import MDTypography from "qqq/components/Temporary/MDTypography"; import BarChart from "qqq/pages/dashboards/Widgets/BarChart"; -import LineChart from "qqq/pages/dashboards/Widgets/LineChart"; +import DefaultLineChart from "qqq/pages/dashboards/Widgets/DefaultLineChart"; +import HorizontalBarChart from "qqq/pages/dashboards/Widgets/HorizontalBarChart"; import MultiStatisticsCard from "qqq/pages/dashboards/Widgets/MultiStatisticsCard"; import ParentWidget from "qqq/pages/dashboards/Widgets/ParentWidget"; import QuickSightChart from "qqq/pages/dashboards/Widgets/QuickSightChart"; import RecordGridWidget from "qqq/pages/dashboards/Widgets/RecordGridWidget"; +import SimpleStatisticsCard from "qqq/pages/dashboards/Widgets/SimpleStatisticsCard"; import StepperCard from "qqq/pages/dashboards/Widgets/StepperCard"; import TableCard from "qqq/pages/dashboards/Widgets/TableCard"; import Widget from "qqq/pages/dashboards/Widgets/Widget"; import ProcessRun from "qqq/pages/process-run"; import QClient from "qqq/utils/QClient"; + const qController = QClient.getInstance(); interface Props @@ -49,7 +52,7 @@ interface Props widgetMetaDataList: QWidgetMetaData[]; entityPrimaryKey?: string; omitWrappingGridContainer: boolean; - areChildren?: boolean; + areChildren?: boolean childUrlParams?: string } @@ -118,10 +121,11 @@ function DashboardWidgets({widgetMetaDataList, entityPrimaryKey, omitWrappingGri const renderWidget = (widgetMetaData: QWidgetMetaData, i: number): JSX.Element => { return ( - + { widgetMetaData.type === "parentWidget" && ( ) } + { + widgetMetaData.type === "statistics" && ( + widgetData && widgetData[i] && ( + + ) + ) + } { widgetMetaData.type === "quickSightChart" && ( @@ -204,16 +220,28 @@ function DashboardWidgets({widgetMetaDataList, entityPrimaryKey, omitWrappingGri /> ) } + { + widgetMetaData.type === "horizontalBarChart" && ( + widgetData && widgetData[i] && widgetData[i].chartData && ( + + ) + ) + } { widgetMetaData.type === "lineChart" && ( - widgetData && widgetData[i] ? ( - { - widgetData[i].lineChartData.datasets.map((dataSet: any) => ( + widgetData[i].chartData.datasets.map((dataSet: any) => ( )) } @@ -221,7 +249,9 @@ function DashboardWidgets({widgetMetaDataList, entityPrimaryKey, omitWrappingGri )} - chart={widgetData[i].lineChartData as { labels: string[]; datasets: { label: string; color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark"; data: number[]; }[]; }} + data={widgetData[i].chartData as { labels: string[]; datasets: { label: string; color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark"; data: number[]; }[]; }} + isYAxisCurrency={widgetData[i].isYAxisCurrency} + isChild={areChildren} /> ) : null ) @@ -248,7 +278,7 @@ function DashboardWidgets({widgetMetaDataList, entityPrimaryKey, omitWrappingGri omitWrappingGridContainer ? renderWidget(widgetMetaData, i) : - + {renderWidget(widgetMetaData, i)} )) diff --git a/src/qqq/pages/dashboards/Widgets/Configs/HorizontalBarChartConfigs.ts b/src/qqq/pages/dashboards/Widgets/Configs/HorizontalBarChartConfigs.ts deleted file mode 100644 index 086e591..0000000 --- a/src/qqq/pages/dashboards/Widgets/Configs/HorizontalBarChartConfigs.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2022. Kingsrook, LLC - * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States - * contact@kingsrook.com - * https://github.com/Kingsrook/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -function configs(labels: any, datasets: any) -{ - return { - data: { - labels, - datasets: [...datasets], - }, - options: { - indexAxis: "y", - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - display: false, - }, - }, - scales: { - y: { - grid: { - drawBorder: false, - display: true, - drawOnChartArea: true, - drawTicks: false, - borderDash: [5, 5], - color: "#c1c4ce5c", - }, - ticks: { - display: true, - padding: 10, - color: "#9ca2b7", - font: { - size: 14, - weight: 300, - family: "Roboto", - style: "normal", - lineHeight: 2, - }, - }, - }, - x: { - grid: { - drawBorder: false, - display: false, - drawOnChartArea: true, - drawTicks: true, - color: "#c1c4ce5c", - }, - ticks: { - display: true, - color: "#9ca2b7", - padding: 10, - font: { - size: 14, - weight: 300, - family: "Roboto", - style: "normal", - lineHeight: 2, - }, - }, - }, - }, - }, - }; -} - -export default configs; diff --git a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx index 4dde68e..f14e06a 100644 --- a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx @@ -52,6 +52,15 @@ const options = { legend: { display: false, }, + tooltip: { + enabled: true, + callbacks: { + label: function(context:any) + { + return(context.parsed.x); + } + } + } }, interaction: { intersect: false, @@ -78,6 +87,10 @@ const options = { style: "normal", lineHeight: 2, }, + callback: function(value: any, index: any, values: any) + { + return value; + } }, }, x: { @@ -116,6 +129,8 @@ interface Props }; title?: string; height?: string | number; + isYAxisCurrency?: boolean; + isChild?: boolean; data: DefaultLineChartData; [key: string]: any; @@ -128,7 +143,7 @@ DefaultLineChart.defaultProps = { }; -function DefaultLineChart({icon, title, height, data}: Props): JSX.Element +function DefaultLineChart({icon, title, height, data, isYAxisCurrency, isChild}: Props): JSX.Element { const allBackgroundColors = ["info", "warning", "primary", "success", "error", "secondary", "dark"]; if (data && data.datasets) @@ -158,6 +173,27 @@ function DefaultLineChart({icon, title, height, data}: Props): JSX.Element })) : []; + let customOptions = options; + if(isYAxisCurrency) + { + customOptions.scales.y.ticks = + { + ... customOptions.scales.y.ticks, + callback: function(value: any, index: any, values: any) + { + return value.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 0}); + } + } + customOptions.plugins.tooltip.callbacks = + { + ... customOptions.plugins.tooltip.callbacks, + label: function(context:any) + { + return " " + context.parsed.y.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 2}); + } + } + } + let fullData = {}; if (data) { @@ -169,6 +205,7 @@ function DefaultLineChart({icon, title, height, data}: Props): JSX.Element const renderChart = ( + {title ? ( {icon.component && ( @@ -190,7 +227,12 @@ function DefaultLineChart({icon, title, height, data}: Props): JSX.Element )} - {title && {title}} + {isChild ? ( + title && {title} + ) : ( + title && {title} + ) + } @@ -224,7 +266,11 @@ function DefaultLineChart({icon, title, height, data}: Props): JSX.Element ); - return title ? {renderChart} : renderChart; + return title ? + + {renderChart} + + : renderChart; } export default DefaultLineChart; diff --git a/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx b/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx index 6e928e0..63eefbf 100644 --- a/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx @@ -40,6 +40,15 @@ const options = { legend: { display: false, }, + tooltip: { + enabled: true, + callbacks: { + label: function(context:any) + { + return(context.parsed.x); + } + } + } }, scales: { y: { @@ -75,7 +84,7 @@ const options = { ticks: { display: true, color: "#9ca2b7", - padding: 10, + padding: 0, font: { size: 14, weight: 300, @@ -83,6 +92,10 @@ const options = { style: "normal", lineHeight: 2, }, + callback: function(value: any, index: any, values: any) + { + return value; + } }, }, }, @@ -101,12 +114,13 @@ interface Props title?: string; description?: string | ReactNode; height?: string | number; + isCurrency?: boolean; data: GenericChartData; [key: string]: any; } -function HorizontalBarChart({icon, title, description, height, data}: Props): JSX.Element +function HorizontalBarChart({icon, title, description, height, data, isCurrency}: Props): JSX.Element { const chartDatasets = data.datasets ? data.datasets.map((dataset) => ({ @@ -114,11 +128,11 @@ function HorizontalBarChart({icon, title, description, height, data}: Props): JS weight: 5, borderWidth: 0, borderRadius: 4, - backgroundColor: colors[dataset.color] - ? colors[dataset.color || "dark"].main - : colors.dark.main, + backgroundColor: dataset?.color + ? dataset.color + : colors.info.main, fill: false, - maxBarThickness: 35, + maxBarThickness: 15, })) : []; @@ -131,10 +145,32 @@ function HorizontalBarChart({icon, title, description, height, data}: Props): JS }; } + let customOptions = options; + if(isCurrency) + { + customOptions.scales.x.ticks = + { + ... customOptions.scales.x.ticks, + callback: function(value: any, index: any, values: any) + { + return value.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 0}); + } + } + customOptions.plugins.tooltip.callbacks = + { + ... customOptions.plugins.tooltip.callbacks, + label: function(context:any) + { + return context.parsed.x.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 0}); + } + } + } + + const renderChart = ( - + {title || description ? ( - + {icon.component && ( ( - + ), diff --git a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx index 4eff6dd..f9f7eb3 100644 --- a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx +++ b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx @@ -54,11 +54,12 @@ interface Props label: string; data: ParentWidgetData; reloadWidgetCallback?: (widgetIndex: number, params: string) => void; + entityPrimaryKey?: string; } const qController = QClient.getInstance(); -function ParentWidget({widgetIndex, label, data, reloadWidgetCallback}: Props, ): JSX.Element +function ParentWidget({widgetIndex, label, data, reloadWidgetCallback, entityPrimaryKey}: Props, ): JSX.Element { const [childUrlParams, setChildUrlParams] = useState(""); const [qInstance, setQInstance] = useState(null as QInstance); @@ -154,7 +155,7 @@ function ParentWidget({widgetIndex, label, data, reloadWidgetCallback}: Props, ) - + { label && ( @@ -165,7 +166,7 @@ function ParentWidget({widgetIndex, label, data, reloadWidgetCallback}: Props, ) } - + { data?.dropdownDataList?.map((dropdownData: any, index: number) => @@ -182,7 +183,7 @@ function ParentWidget({widgetIndex, label, data, reloadWidgetCallback}: Props, ) - + ); diff --git a/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx b/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx index f248a6b..f3a75a2 100644 --- a/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx +++ b/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx @@ -31,6 +31,7 @@ interface Props title: string; data: StatisticsCardData; increaseIsGood: boolean; + isCurrency?: boolean; dropdown?: { action: (...args: any) => void; menu: ReactNode; @@ -40,7 +41,7 @@ interface Props [key: string]: any; } -function SimpleStatisticsCard({title, data, increaseIsGood, dropdown}: Props): JSX.Element +function SimpleStatisticsCard({title, data, increaseIsGood, isCurrency, dropdown}: Props): JSX.Element { const {count, percentageAmount, percentageLabel} = data; @@ -65,10 +66,10 @@ function SimpleStatisticsCard({title, data, increaseIsGood, dropdown}: Props): J } return ( - + - + { count ? ( - - {count.toLocaleString()} - + isCurrency ? ( + + {count.toLocaleString("en-US", {style: "currency", currency: "USD"})} + + ) : ( + + + {count.toLocaleString("en-US", {style: "currency", currency: "USD"})} + + ) ) : null } @@ -99,8 +107,8 @@ function SimpleStatisticsCard({title, data, increaseIsGood, dropdown}: Props): J - - {dropdown && ( + {dropdown && ( + {dropdown.menu} - )} - + + )}