diff --git a/package.json b/package.json index 86cf182..52c73bf 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@fullcalendar/interaction": "5.10.0", "@fullcalendar/react": "5.10.0", "@fullcalendar/timegrid": "5.10.0", - "@kingsrook/qqq-frontend-core": "1.0.38", + "@kingsrook/qqq-frontend-core": "1.0.39", "@mui/icons-material": "5.4.1", "@mui/material": "5.4.1", "@mui/styled-engine": "5.4.1", diff --git a/public/flags/AU.png b/public/flags/AU.png new file mode 100644 index 0000000..13fd089 Binary files /dev/null and b/public/flags/AU.png differ diff --git a/public/flags/BR.png b/public/flags/BR.png new file mode 100644 index 0000000..91e3862 Binary files /dev/null and b/public/flags/BR.png differ diff --git a/public/flags/DE.png b/public/flags/DE.png new file mode 100644 index 0000000..5029361 Binary files /dev/null and b/public/flags/DE.png differ diff --git a/public/flags/GB.png b/public/flags/GB.png new file mode 100644 index 0000000..b2f1b3b Binary files /dev/null and b/public/flags/GB.png differ diff --git a/public/flags/US.png b/public/flags/US.png new file mode 100644 index 0000000..5b42a56 Binary files /dev/null and b/public/flags/US.png differ diff --git a/src/App.tsx b/src/App.tsx index 296db35..d32ffc7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -83,7 +83,6 @@ function getStaticRoutes() }, ], }, - {type: "divider", key: "divider-1"}, ]; } @@ -411,14 +410,35 @@ export default function App() const sideNavAppList = [] as any[]; const appRoutesList = [] as any[]; + const mainDashboardsApp = {} as any; + + /////////////////////////////////////////////////////////////////////////////////// + // iterate throught the list to find the 'main dashboard so we can put it first' // + /////////////////////////////////////////////////////////////////////////////////// for (let i = 0; i < metaData.appTree.length; i++) { const app = metaData.appTree[i]; + if(app.name === "mainDashboards") + { + addAppToSideNavList(app, sideNavAppList, "", 0); + addAppToAppRoutesList(metaData, app, appRoutesList, "", 0); + sideNavAppList.push({type: "divider", key: "divider-1"}); + break; + } + } + for (let i = 0; i < metaData.appTree.length; i++) + { + const app = metaData.appTree[i]; + if(app.name === "mainDashboards") + { + continue; + } + addAppToSideNavList(app, sideNavAppList, "", 0); addAppToAppRoutesList(metaData, app, appRoutesList, "", 0); } - const newSideNavRoutes = getStaticRoutes(); + const newSideNavRoutes = []; // getStaticRoutes(); // @ts-ignore newSideNavRoutes.unshift(profileRoutes); for (let i = 0; i < sideNavAppList.length; i++) diff --git a/src/qqq/components/DashboardWidgets.tsx b/src/qqq/components/DashboardWidgets.tsx index 9725d42..f78167e 100644 --- a/src/qqq/components/DashboardWidgets.tsx +++ b/src/qqq/components/DashboardWidgets.tsx @@ -37,11 +37,15 @@ import FieldValueListWidget from "qqq/pages/dashboards/Widgets/FieldValueListWid 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 PieChartCard from "qqq/pages/dashboards/Widgets/PieChartCard"; 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 SmallLineChart from "qqq/pages/dashboards/Widgets/SmallLineChart"; +import StatisticsCard from "qqq/pages/dashboards/Widgets/StatisticsCard"; import StepperCard from "qqq/pages/dashboards/Widgets/StepperCard"; import TableCard from "qqq/pages/dashboards/Widgets/TableCard"; +import USMapWidget from "qqq/pages/dashboards/Widgets/USMapWidget"; import Widget from "qqq/pages/dashboards/Widgets/Widget"; import ProcessRun from "qqq/pages/process-run"; import QClient from "qqq/utils/QClient"; @@ -98,9 +102,9 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit widgetData[i] = {}; (async () => { - console.log(`widgets: ${getQueryParams(null)}`) widgetData[i] = await qController.widget(widgetMetaDataList[i].name, getQueryParams(null)); setWidgetCounter(widgetCounter + 1); + console.log(`widget data: ${JSON.stringify(widgetData[i])}`) forceUpdate(); })(); } @@ -147,7 +151,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit } return params; - }; + } const widgetCount = widgetMetaDataList ? widgetMetaDataList.length : 0; @@ -158,6 +162,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit { widgetMetaData.type === "parentWidget" && ( ) } + { + widgetMetaData.type === "table" && ( + reloadWidget(i, data)} + isChild={areChildren} + > + reloadWidget(i, data)} + widgetIndex={i} + /> + + ) + } { widgetMetaData.type === "process" && widgetData[i]?.processMetaData && ( + ) + } + { + widgetMetaData.type === "simpleStatistics" && ( widgetData && widgetData[i] && ( + ) + ) + } { widgetMetaData.type === "quickSightChart" && ( @@ -255,8 +300,18 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit widgetMetaData.type === "barChart" && ( + ) + } + { + widgetMetaData.type === "pieChart" && ( + ) @@ -270,14 +325,12 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit } { widgetMetaData.type === "horizontalBarChart" && ( - widgetData && widgetData[i] && widgetData[i].chartData && ( - - ) + ) } { diff --git a/src/qqq/components/Temporary/DataTable/index.tsx b/src/qqq/components/Temporary/DataTable/index.tsx index 75bfa55..73de877 100644 --- a/src/qqq/components/Temporary/DataTable/index.tsx +++ b/src/qqq/components/Temporary/DataTable/index.tsx @@ -38,12 +38,7 @@ import MDInput from "qqq/components/Temporary/MDInput"; import MDPagination from "qqq/components/Temporary/MDPagination"; import MDTypography from "qqq/components/Temporary/MDTypography"; import ImageCell from "qqq/pages/dashboards/Tables/ImageCell"; - -export interface TableDataInput -{ - columns: { [key: string]: any }[]; - rows: { [key: string]: any }[]; -} +import {TableDataInput} from "qqq/pages/dashboards/Widgets/TableCard"; interface Props { diff --git a/src/qqq/pages/dashboards/CarrierPerformance.tsx b/src/qqq/pages/dashboards/CarrierPerformance.tsx index faba779..88d36a6 100644 --- a/src/qqq/pages/dashboards/CarrierPerformance.tsx +++ b/src/qqq/pages/dashboards/CarrierPerformance.tsx @@ -29,7 +29,6 @@ import QContext from "QContext"; import DashboardLayout from "qqq/components/DashboardLayout"; import Footer from "qqq/components/Footer"; import Navbar from "qqq/components/Navbar"; -import {TableDataInput} from "qqq/components/Temporary/DataTable"; import MDBox from "qqq/components/Temporary/MDBox"; import ShipmentsByWarehouseTable from "qqq/pages/dashboards/Tables/ShipmentsByWarehouseTable"; import {GenericChartData} from "qqq/pages/dashboards/Widgets/Data/GenericChartData"; @@ -40,7 +39,7 @@ import {PieChartData} from "qqq/pages/dashboards/Widgets/PieChart"; import PieChartCard from "qqq/pages/dashboards/Widgets/PieChartCard"; import SimpleStatisticsCard from "qqq/pages/dashboards/Widgets/SimpleStatisticsCard"; import {StatisticsCardData} from "qqq/pages/dashboards/Widgets/StatisticsCard"; -import TableCard from "qqq/pages/dashboards/Widgets/TableCard"; +import TableCard, {TableDataInput} from "qqq/pages/dashboards/Widgets/TableCard"; import QClient from "qqq/utils/QClient"; const qController = QClient.getInstance(); diff --git a/src/qqq/pages/dashboards/Overview.tsx b/src/qqq/pages/dashboards/Overview.tsx index c9d2c72..2fbfde3 100644 --- a/src/qqq/pages/dashboards/Overview.tsx +++ b/src/qqq/pages/dashboards/Overview.tsx @@ -47,7 +47,6 @@ function Overview(): JSX.Element ////////////////////////////////// // shipments by day widget data // ////////////////////////////////// - const [shipmentsByDayTitle, setShipmentsByDayTitle] = useState(""); const [shipmentsByDayDescription, setShipmentsByDayDescription] = useState(""); const [shipmentsByDayData, setShipmentsByDayData] = useState({} as GenericChartDataSingleDataset); @@ -135,7 +134,6 @@ function Overview(): JSX.Element } const description = "Over the last week there have been " + daysOverAverage.toLocaleString() + (daysOverAverage == 1 ? " day" : " days") + " with total shipments greater than the daily average of " + average.toLocaleString() + " shipments."; - setShipmentsByDayTitle(widgetData.title); setShipmentsByDayData(widgetData.chartData); setShipmentsByDayDescription(description); })(); diff --git a/src/qqq/pages/dashboards/Widgets/BarChart.tsx b/src/qqq/pages/dashboards/Widgets/BarChart.tsx index cb09524..bae41ba 100644 --- a/src/qqq/pages/dashboards/Widgets/BarChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/BarChart.tsx @@ -19,6 +19,7 @@ * along with this program. If not, see . */ +import Box from "@mui/material/Box"; import Card from "@mui/material/Card"; import Divider from "@mui/material/Divider"; import Icon from "@mui/material/Icon"; @@ -142,44 +143,47 @@ function BarChart({color, title, description, date, data}: Props): JSX.Element const {chartData} = getChartData(data?.labels, data?.dataset); return ( - - - {useMemo( - () => ( - - + + + + + {useMemo( + () => ( + + + + ), + [data, color] + )} + + + {title} + + + {parse(description)} + + + + + schedule + + + {date} + - ), - [data, color] - )} - - - {title} - - - {parse(description)} - - - - - schedule - - - {date} - - - + + ); } diff --git a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx index 9e7f579..8830dcd 100644 --- a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx @@ -57,7 +57,7 @@ const options = { callbacks: { label: function(context:any) { - return(context.parsed.x); + return(" " + Number(context.parsed.y).toLocaleString()); } } } @@ -90,7 +90,7 @@ const options = { }, callback: function(value: any, index: any, values: any) { - return value; + return value.toLocaleString(); } }, }, diff --git a/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx b/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx index d8c619b..72063ea 100644 --- a/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/HorizontalBarChart.tsx @@ -19,6 +19,7 @@ * along with this program. If not, see . */ +import Box from "@mui/material/Box"; import Card from "@mui/material/Card"; import Icon from "@mui/material/Icon"; import {ReactNode, useMemo} from "react"; @@ -48,7 +49,7 @@ const options = { return(context.parsed.x); } } - } + }, }, scales: { y: { @@ -122,27 +123,30 @@ interface Props function HorizontalBarChart({icon, title, description, height, data, isCurrency}: Props): JSX.Element { - const chartDatasets = data.datasets - ? data.datasets.map((dataset) => ({ - ...dataset, - weight: 5, - borderWidth: 0, - borderRadius: 4, - backgroundColor: dataset?.color - ? dataset.color - : colors.info.main, - fill: false, - maxBarThickness: 15, - })) - : []; - let fullData = {}; - if (data) + if(data && data.datasets) { - fullData = { - labels: data.labels, - datasets: chartDatasets - }; + const chartDatasets = data.datasets + ? data.datasets.map((dataset) => ({ + ...dataset, + weight: 5, + borderWidth: 0, + borderRadius: 4, + backgroundColor: dataset?.color + ? dataset.color + : colors.info.main, + fill: false, + maxBarThickness: 15, + })) + : []; + + if (data) + { + fullData = { + labels: data.labels, + datasets: chartDatasets + }; + } } let customOptions = options; @@ -166,10 +170,9 @@ function HorizontalBarChart({icon, title, description, height, data, isCurrency} } } - const renderChart = ( - {title || description ? ( + {title || description && ( {icon.component && ( - ) : null} + )} {useMemo( () => ( - + { + data && data?.datasets && data?.datasets.length > 0 ?( + + ):( + No data was provided to this chart + ) + } ), [data, height] diff --git a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx index e1f3a75..0d968b9 100644 --- a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx +++ b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx @@ -21,13 +21,10 @@ import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance"; import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData"; -import {Box, Typography} from "@mui/material"; -import Card from "@mui/material/Card"; -import Grid from "@mui/material/Grid"; +import {Box} from "@mui/material"; import React, {useEffect, useState} from "react"; import DashboardWidgets from "qqq/components/DashboardWidgets"; -import DropdownMenu from "qqq/pages/dashboards/Widgets/Components/DropdownMenu"; -import Widget, {Dropdown, LabelComponent} from "qqq/pages/dashboards/Widgets/Widget"; +import Widget from "qqq/pages/dashboards/Widgets/Widget"; import QClient from "qqq/utils/QClient"; @@ -44,6 +41,7 @@ export interface ParentWidgetData }[][]; childWidgetNameList: string[]; dropdownNeedsSelectedText?: string; + icon?: string; } @@ -54,6 +52,7 @@ interface Props { widgetIndex: number; label: string; + icon?: string; data: ParentWidgetData; reloadWidgetCallback?: (widgetIndex: number, params: string) => void; entityPrimaryKey?: string; @@ -62,7 +61,7 @@ interface Props const qController = QClient.getInstance(); -function ParentWidget({widgetIndex, label, data, reloadWidgetCallback, entityPrimaryKey, tableName}: Props, ): JSX.Element +function ParentWidget({widgetIndex, label, icon, data, reloadWidgetCallback, entityPrimaryKey, tableName}: Props, ): JSX.Element { const [childUrlParams, setChildUrlParams] = useState(""); const [qInstance, setQInstance] = useState(null as QInstance); @@ -93,16 +92,19 @@ function ParentWidget({widgetIndex, label, data, reloadWidgetCallback, entityPri const parentReloadWidgetCallback = (data: string) => { setChildUrlParams(data); + reloadWidgetCallback(widgetIndex, data); } + // @ts-ignore return ( - + diff --git a/src/qqq/pages/dashboards/Widgets/PieChartCard.tsx b/src/qqq/pages/dashboards/Widgets/PieChartCard.tsx index ad4fbc0..a360724 100644 --- a/src/qqq/pages/dashboards/Widgets/PieChartCard.tsx +++ b/src/qqq/pages/dashboards/Widgets/PieChartCard.tsx @@ -48,8 +48,8 @@ function PieChartCard({title, description, data}: Props): JSX.Element } return ( - - + + {title} @@ -72,15 +72,19 @@ function PieChartCard({title, description, data}: Props): JSX.Element - - - - - {parse(description)} - - - - + { + description && ( + + + + + {parse(description)} + + + + + ) + } ); diff --git a/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx b/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx index f3a75a2..f4f6a7b 100644 --- a/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx +++ b/src/qqq/pages/dashboards/Widgets/SimpleStatisticsCard.tsx @@ -82,7 +82,7 @@ function SimpleStatisticsCard({title, data, increaseIsGood, isCurrency, dropdown { - count ? ( + count !== undefined ? ( isCurrency ? ( {count.toLocaleString("en-US", {style: "currency", currency: "USD"})} @@ -90,21 +90,29 @@ function SimpleStatisticsCard({title, data, increaseIsGood, isCurrency, dropdown ) : ( - {count.toLocaleString("en-US", {style: "currency", currency: "USD"})} + {count.toLocaleString()} ) ) : null } - - {percentageString}  - - {percentageLabel} - - + { + count !== undefined ? ( + + {percentageString}  + + {percentageLabel} + + + ):( + + Loading. + + ) + } {dropdown && ( diff --git a/src/qqq/pages/dashboards/Widgets/SmallLineChart.tsx b/src/qqq/pages/dashboards/Widgets/SmallLineChart.tsx index 34302df..95dd196 100644 --- a/src/qqq/pages/dashboards/Widgets/SmallLineChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/SmallLineChart.tsx @@ -19,9 +19,8 @@ * along with this program. If not, see . */ +import Box from "@mui/material/Box"; import Card from "@mui/material/Card"; -import Divider from "@mui/material/Divider"; -import Icon from "@mui/material/Icon"; import parse from "html-react-parser"; import {useMemo} from "react"; import {Line} from "react-chartjs-2"; @@ -57,47 +56,40 @@ function SmallLineChart({color, title, description, date, chart}: Props): JSX.El { const {data, options} = configs(chart?.labels || [], chart?.dataset || {}); - console.log(`DATA: ${JSON.stringify(data)}`); - return ( - - - {useMemo( - () => ( - - - - ), - [chart, color] - )} - - - {title} - - - {parse(description)} - - - - - schedule + + + + + + {useMemo( + () => ( + + + + ), + [chart, color] + )} + + + {title} - - {date} + + {parse(description)} - - + + ); } diff --git a/src/qqq/pages/dashboards/Widgets/StatisticsCard.tsx b/src/qqq/pages/dashboards/Widgets/StatisticsCard.tsx index d20fe5e..2816586 100644 --- a/src/qqq/pages/dashboards/Widgets/StatisticsCard.tsx +++ b/src/qqq/pages/dashboards/Widgets/StatisticsCard.tsx @@ -88,7 +88,8 @@ function StatisticsCard({data, color, icon, increaseIsGood}: Props): JSX.Element } return ( - + + - { percentageAmount !== undefined && percentageAmount !== 0 ? ( - + + . */ -import {Icon, Skeleton} from "@mui/material"; -import Card from "@mui/material/Card"; -import Grid from "@mui/material/Grid"; -import Menu from "@mui/material/Menu"; -import MenuItem from "@mui/material/MenuItem"; +import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance"; +import {Skeleton} from "@mui/material"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableContainer from "@mui/material/TableContainer"; import TableRow from "@mui/material/TableRow"; import parse from "html-react-parser"; import React, {useEffect, useState} from "react"; -import {NavLink} from "react-router-dom"; -import DataTable, {TableDataInput} from "qqq/components/Temporary/DataTable"; +import DataTable from "qqq/components/Temporary/DataTable"; import DataTableBodyCell from "qqq/components/Temporary/DataTable/DataTableBodyCell"; import DataTableHeadCell from "qqq/components/Temporary/DataTable/DataTableHeadCell"; import DefaultCell from "qqq/components/Temporary/DefaultCell"; import MDBox from "qqq/components/Temporary/MDBox"; import MDTypography from "qqq/components/Temporary/MDTypography"; +import QClient from "qqq/utils/QClient"; + + +////////////////////////////////////// +// structure of expected table data // +////////////////////////////////////// +export interface TableDataInput +{ + columns: { [key: string]: any }[]; + rows: { [key: string]: any }[]; +} ///////////////////////// @@ -49,130 +56,39 @@ interface Props linkURL?: string; noRowsFoundHTML?: string; data: TableDataInput; - dropdownOptions?: { - id: string, - name: string - }[]; - reloadWidgetCallback?: (widgetIndex: number, params: string) => void; + reloadWidgetCallback?: (params: string) => void; widgetIndex?: number; isChild?: boolean; [key: string]: any; } -function TableCard({title, linkText, linkURL, noRowsFoundHTML, data, dropdownOptions, reloadWidgetCallback, widgetIndex, isChild}: Props): JSX.Element +const qController = QClient.getInstance(); +function TableCard({noRowsFoundHTML, data, reloadWidgetCallback}: Props): JSX.Element { - const openArrowIcon = "arrow_drop_down"; - const closeArrowIcon = "arrow_drop_up"; - const [dropdown, setDropdown] = useState(null); - const [dropdownValue, setDropdownValue] = useState(""); - const [dropdownLabel, setDropdownLabel] = useState(""); - const [dropdownIcon, setDropdownIcon] = useState(openArrowIcon); - - // console.log(`data: ${JSON.stringify(data?.rows)}`); - // console.log(`bool: ${data && data?.columns && !data?.rows}`); - // console.log(`norowsfound: ${noRowsFoundHTML}`); - - const openDropdown = ({currentTarget}: any) => - { - setDropdown(currentTarget); - setDropdownIcon(closeArrowIcon); - }; - const closeDropdown = ({currentTarget}: any) => - { - setDropdown(null); - setDropdownValue(currentTarget.innerText || dropdownValue); - setDropdownIcon(openArrowIcon); - reloadWidgetCallback(widgetIndex, null); - }; - - const renderMenu = (state: any, open: any, close: any, icon: string) => ( - dropdownOptions && ( - - {icon} - - { - dropdownOptions.map((optionMap, index: number) => - {optionMap["name"]} - ) - } - - - ) - ); + const [qInstance, setQInstance] = useState(null as QInstance); useEffect(() => { - if (dropdownOptions) + (async () => { - setDropdownValue(dropdownOptions[0]["id"]); - setDropdownLabel(dropdownOptions[0]["name"]); - - } - }, [dropdownOptions]); + const newQInstance = await qController.loadMetaData(); + setQInstance(newQInstance); + })(); + }, []); return ( - - - - - - {title} - - - - - { - linkText && ( - - {linkText} - - ) - } - - - {dropdownOptions && ( - - - Billing Period: - - - {dropdownLabel} - - {renderMenu(dropdown, openDropdown, closeDropdown, dropdownIcon)} - - )} - - - - - { - data && data.columns && !noRowsFoundHTML ? ( - - ) : noRowsFoundHTML ? ( + + { + data && data.columns && !noRowsFoundHTML ? + + : noRowsFoundHTML ? - ) : ( + : @@ -211,10 +127,8 @@ function TableCard({title, linkText, linkURL, noRowsFoundHTML, data, dropdownOpt
- ) - } -
-
+ } +
); } diff --git a/src/qqq/pages/dashboards/Widgets/USMapWidget.tsx b/src/qqq/pages/dashboards/Widgets/USMapWidget.tsx new file mode 100644 index 0000000..88ef558 --- /dev/null +++ b/src/qqq/pages/dashboards/Widgets/USMapWidget.tsx @@ -0,0 +1,146 @@ +/* + * 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 . + */ + +import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance"; +import {Box, Grid} from "@mui/material"; +import {VectorMap} from "@react-jvectormap/core"; +import {usAea} from "@react-jvectormap/unitedstates"; +import React, {useEffect, useState} from "react"; +import QClient from "qqq/utils/QClient"; + + +//////////////////////////////////////////////// +// structure of expected US and A widget data // +//////////////////////////////////////////////// +export interface MapMarkerData +{ + name: string; + latitude: number; + longitude: number; +} +export interface USMapWidgetData +{ + height: string; + markers?: MapMarkerData[]; +} + + +//////////////////////////////////// +// define properties and defaults // +//////////////////////////////////// +interface Props +{ + widgetIndex: number; + label: string; + icon?: string; + reloadWidgetCallback?: (widgetIndex: number, params: string) => void; + data: USMapWidgetData; +} + + +const qController = QClient.getInstance(); +function USMapWidget(props: Props, ): JSX.Element +{ + const [qInstance, setQInstance] = useState(null as QInstance); + + useEffect(() => + { + (async () => + { + const newQInstance = await qController.loadMetaData(); + setQInstance(newQInstance); + })(); + }, []); + + console.log(JSON.stringify(props)) + + return ( + + + { + props.data?.height && ( + + false} + onMarkerTipShow={() => false} + /> + + ) + } + + + + ); +} + +export default USMapWidget; diff --git a/src/qqq/pages/dashboards/Widgets/Widget.tsx b/src/qqq/pages/dashboards/Widgets/Widget.tsx index 7987752..3c1aeb2 100644 --- a/src/qqq/pages/dashboards/Widgets/Widget.tsx +++ b/src/qqq/pages/dashboards/Widgets/Widget.tsx @@ -23,19 +23,18 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QT import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import Card from "@mui/material/Card"; -import Modal from "@mui/material/Modal"; +import Icon from "@mui/material/Icon"; import Typography from "@mui/material/Typography"; import React, {useEffect, useState} from "react"; import {Link, useNavigate} from "react-router-dom"; -import DashboardWidgets from "qqq/components/DashboardWidgets"; -import EntityForm from "qqq/components/EntityForm"; +import colors from "qqq/components/Temporary/colors"; import DropdownMenu, {DropdownOption} from "qqq/pages/dashboards/Widgets/Components/DropdownMenu"; export interface WidgetData { - dropdownLabelList: string[]; - dropdownNameList: string[]; - dropdownDataList: { + dropdownLabelList?: string[]; + dropdownNameList?: string[]; + dropdownDataList?: { id: string, label: string }[][]; @@ -45,15 +44,20 @@ export interface WidgetData interface Props { + icon?: string; label: string; labelAdditionalComponentsLeft: LabelComponent[]; labelAdditionalComponentsRight: LabelComponent[]; widgetData?: WidgetData; children: JSX.Element; reloadWidgetCallback?: (params: string) => void; + isChild?: boolean; + isCard?: boolean; } Widget.defaultProps = { + isCard: true, + isChild: false, label: null, widgetData: {}, labelAdditionalComponentsLeft: [], @@ -246,44 +250,70 @@ function Widget(props: React.PropsWithChildren): JSX.Element } }, [counter]); - return ( - <> - - - - - {props.label} - - { - props.labelAdditionalComponentsLeft.map((component, i) => + const widgetContent = + + { + (props.icon || props.label) && ( + + { - return ({renderComponent(component)}); - }) - } - - - { - effectiveLabelAdditionalComponentsRight.map((component, i) => - { - return ({renderComponent(component)}); - }) - } - - - { - props.widgetData?.dropdownNeedsSelectedText ? ( - - - {props.widgetData?.dropdownNeedsSelectedText} + props.icon && ( + + + {props.icon} + + + ) + } + + {props.label} + { + props.labelAdditionalComponentsLeft.map((component, i) => + { + return ({renderComponent(component)}); + }) + } - ) : ( - props.children - ) - } - - - ); + + { + effectiveLabelAdditionalComponentsRight.map((component, i) => + { + return ({renderComponent(component)}); + }) + } + + + ) + } + { + props.widgetData?.dropdownNeedsSelectedText ? ( + + + {props.widgetData?.dropdownNeedsSelectedText} + + + ) : ( + props.children + ) + } + ; + + return props.isCard ? {widgetContent} : widgetContent; } export default Widget;