From e362e7be4444f012302eb0b6a2a043892d6bad02 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 14 Dec 2022 16:45:33 -0600 Subject: [PATCH] Add dropdowns to fieldValueList widget; various cleanups re: widgets --- src/qqq/components/DashboardWidgets.tsx | 3 +- .../Widgets/Components/DropdownMenu.tsx | 3 + .../dashboards/Widgets/DefaultLineChart.tsx | 1 + .../Widgets/FieldValueListWidget.tsx | 14 +- .../pages/dashboards/Widgets/LineChart.tsx | 209 ------------------ .../pages/dashboards/Widgets/ParentWidget.tsx | 2 - .../dashboards/Widgets/RecordGridWidget.tsx | 39 +++- src/qqq/pages/dashboards/Widgets/Widget.tsx | 2 +- src/qqq/pages/entity-view/EntityView.tsx | 16 +- 9 files changed, 71 insertions(+), 218 deletions(-) delete mode 100644 src/qqq/pages/dashboards/Widgets/LineChart.tsx diff --git a/src/qqq/components/DashboardWidgets.tsx b/src/qqq/components/DashboardWidgets.tsx index e26995f..9725d42 100644 --- a/src/qqq/components/DashboardWidgets.tsx +++ b/src/qqq/components/DashboardWidgets.tsx @@ -240,7 +240,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit ) @@ -320,6 +320,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit reloadWidget(i, data)} /> ) } diff --git a/src/qqq/pages/dashboards/Widgets/Components/DropdownMenu.tsx b/src/qqq/pages/dashboards/Widgets/Components/DropdownMenu.tsx index 90ed2db..9447751 100644 --- a/src/qqq/pages/dashboards/Widgets/Components/DropdownMenu.tsx +++ b/src/qqq/pages/dashboards/Widgets/Components/DropdownMenu.tsx @@ -61,6 +61,9 @@ function DropdownMenu({label, dropdownOptions, onChangeCallback, sx}: Props): JS sx={{...sx, cursor: "pointer"}} onChange={handleOnChange} renderInput={(params: any) => } + renderOption={(props, option: DropdownOption) => ( +
  • {option.label}
  • + )} /> ) : null diff --git a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx index f14e06a..9e7f579 100644 --- a/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx +++ b/src/qqq/pages/dashboards/Widgets/DefaultLineChart.tsx @@ -68,6 +68,7 @@ const options = { }, scales: { y: { + beginAtZero: true, grid: { drawBorder: false, display: true, diff --git a/src/qqq/pages/dashboards/Widgets/FieldValueListWidget.tsx b/src/qqq/pages/dashboards/Widgets/FieldValueListWidget.tsx index b868358..3fd38e6 100644 --- a/src/qqq/pages/dashboards/Widgets/FieldValueListWidget.tsx +++ b/src/qqq/pages/dashboards/Widgets/FieldValueListWidget.tsx @@ -33,12 +33,22 @@ interface Props { title: string; data: any; + reloadWidgetCallback?: (params: string) => void; } FieldValueListWidget.defaultProps = {}; -function FieldValueListWidget({title, data}: Props): JSX.Element +function FieldValueListWidget({title, data, reloadWidgetCallback}: Props): JSX.Element { + if(data?.dropdownNeedsSelectedText) + { + return ( + +
    +
    + ); + } + if(!data.fields || !data.record) { const skeletons = [75, 50, 90]; @@ -69,7 +79,7 @@ function FieldValueListWidget({title, data}: Props): JSX.Element const fieldIndentLevels = data.fieldIndentLevels ?? {}; return ( - + { fields.map((field: QFieldMetaData, index: number) => ( diff --git a/src/qqq/pages/dashboards/Widgets/LineChart.tsx b/src/qqq/pages/dashboards/Widgets/LineChart.tsx deleted file mode 100644 index 5256e0a..0000000 --- a/src/qqq/pages/dashboards/Widgets/LineChart.tsx +++ /dev/null @@ -1,209 +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 . - */ - -import Card from "@mui/material/Card"; -import Icon from "@mui/material/Icon"; -import {ReactNode, useMemo} from "react"; -import {Line} from "react-chartjs-2"; -import colors from "qqq/components/Temporary/colors"; -import MDBox from "qqq/components/Temporary/MDBox"; -import MDTypography from "qqq/components/Temporary/MDTypography"; -import configs from "qqq/pages/dashboards/Widgets/Configs/LineChartConfigs"; - - -/////////////////////////////////////////// -// structure of expected line chart data // -/////////////////////////////////////////// -export interface LineChartData -{ - labels: string[]; - datasets: { - label: string; - color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark"; - data: number[]; - }[]; -}; - - -//////////////////////// -// line chart options // -//////////////////////// -const options = { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - display: false, - }, - }, - interaction: { - intersect: false, - mode: "index", - }, - scales: { - y: { - grid: { - drawBorder: false, - display: true, - drawOnChartArea: true, - drawTicks: false, - borderDash: [5, 5], - color: "rgba(255, 255, 255, .2)", - }, - ticks: { - display: true, - color: "#f8f9fa", - padding: 10, - font: { - size: 14, - weight: 300, - family: "Roboto", - style: "normal", - lineHeight: 2, - }, - }, - }, - x: { - grid: { - drawBorder: false, - display: false, - drawOnChartArea: false, - drawTicks: false, - borderDash: [5, 5], - }, - ticks: { - display: true, - color: "#f8f9fa", - padding: 10, - font: { - size: 14, - weight: 300, - family: "Roboto", - style: "normal", - lineHeight: 2, - }, - }, - }, - }, -}; - - -////////////////////////////////////////// -// define input properties and defaults // -////////////////////////////////////////// -interface Props -{ - icon?: { - color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark"; - component: ReactNode; - }; - title?: string; - description?: string | ReactNode; - height?: string | number; - chart: { - labels: string[]; - datasets: { - label: string; - color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark"; - data: number[]; - }[]; - }; - - [key: string]: any; -} - -LineChart.defaultProps = { - icon: {color: "info", component: ""}, - title: "", - description: "", - height: "19.125rem", -}; - -function LineChart({icon, title, description, height, chart}: Props): JSX.Element -{ - const chartDatasets = chart.datasets - ? chart.datasets.map((dataset) => ({ - ...dataset, - tension: 0, - pointRadius: 3, - borderWidth: 4, - backgroundColor: "transparent", - fill: true, - pointBackgroundColor: colors[dataset.color] - ? colors[dataset.color || "dark"].main - : colors.dark.main, - borderColor: colors[dataset.color] - ? colors[dataset.color || "dark"].main - : colors.dark.main, - maxBarThickness: 6, - })) - : []; - - const {data} = configs(chart.labels || [], chartDatasets); - - const renderChart = ( - - {title || description ? ( - - {icon.component && ( - - {icon.component} - - )} - - {title && {title}} - - - {description} - - - - - ) : null} - {useMemo( - () => ( - - - - ), - [chart, height] - )} - - ); - - return title || description ? {renderChart} : renderChart; -} - - -export default LineChart; diff --git a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx index 29d778a..e1f3a75 100644 --- a/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx +++ b/src/qqq/pages/dashboards/Widgets/ParentWidget.tsx @@ -66,9 +66,7 @@ function ParentWidget({widgetIndex, label, data, reloadWidgetCallback, entityPri { const [childUrlParams, setChildUrlParams] = useState(""); const [qInstance, setQInstance] = useState(null as QInstance); - const [dropdownData, setDropdownData] = useState([]); const [widgets, setWidgets] = useState([] as any[]); - const [counter, setCounter] = useState(0); useEffect(() => { diff --git a/src/qqq/pages/dashboards/Widgets/RecordGridWidget.tsx b/src/qqq/pages/dashboards/Widgets/RecordGridWidget.tsx index d3b3b7d..f28dc74 100644 --- a/src/qqq/pages/dashboards/Widgets/RecordGridWidget.tsx +++ b/src/qqq/pages/dashboards/Widgets/RecordGridWidget.tsx @@ -21,9 +21,11 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData"; import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord"; -import {DataGridPro} from "@mui/x-data-grid-pro"; +import {DataGridPro, GridCallbackDetails, GridRowParams, MuiEvent} from "@mui/x-data-grid-pro"; import React, {useEffect, useState} from "react"; +import {useNavigate} from "react-router-dom"; import DataGridUtils from "qqq/utils/DataGridUtils"; +import QClient from "qqq/utils/QClient"; import Widget, {AddNewRecordButton, HeaderLink, LabelComponent} from "./Widget"; interface Props @@ -34,10 +36,13 @@ interface Props RecordGridWidget.defaultProps = {}; +const qController = QClient.getInstance(); + function RecordGridWidget({title, data}: Props): JSX.Element { const [rows, setRows] = useState([]); const [columns, setColumns] = useState([]); + const navigate = useNavigate(); useEffect(() => { @@ -59,6 +64,21 @@ function RecordGridWidget({title, data}: Props): JSX.Element const childTablePath = data.tablePath + (data.tablePath.endsWith("/") ? "" : "/") const columns = DataGridUtils.setupGridColumns(tableMetaData, columnsToRender, childTablePath); + //////////////////////////////////////////////////////////////// + // do not not show the foreign-key column of the parent table // + //////////////////////////////////////////////////////////////// + if(data.defaultValuesForNewChildRecords) + { + for (let i = 0; i < columns.length; i++) + { + if(data.defaultValuesForNewChildRecords[columns[i].field]) + { + columns.splice(i, 1); + i-- + } + } + } + setRows(rows); setColumns(columns); } @@ -81,6 +101,21 @@ function RecordGridWidget({title, data}: Props): JSX.Element labelAdditionalComponentsRight.push(new AddNewRecordButton(data.childTableMetaData, data.defaultValuesForNewChildRecords, "Add new", disabledFields)) } + + const handleRowClick = (params: GridRowParams, event: MuiEvent, details: GridCallbackDetails) => + { + (async () => + { + const qInstance = await qController.loadMetaData() + const tablePath = qInstance.getTablePathByName(data.childTableMetaData.name) + if(tablePath) + { + navigate(`${tablePath}/${params.id}`); + } + })(); + }; + + return ( (params.indexRelativeToCurrentPage % 2 === 0 ? "even" : "odd")} + onRowClick={handleRowClick} // getRowHeight={() => "auto"} // maybe nice? wraps values in cells... // components={{Toolbar: CustomToolbar, Pagination: CustomPagination, LoadingOverlay: Loading}} // pinnedColumns={pinnedColumns} @@ -106,7 +142,6 @@ function RecordGridWidget({title, data}: Props): JSX.Element // checkboxSelection // rowCount={totalRecords === null ? 0 : totalRecords} // onPageSizeChange={handleRowsPerPageChange} - // onRowClick={handleRowClick} // onStateChange={handleStateChange} // density={density} // loading={loading} diff --git a/src/qqq/pages/dashboards/Widgets/Widget.tsx b/src/qqq/pages/dashboards/Widgets/Widget.tsx index e46e72d..7987752 100644 --- a/src/qqq/pages/dashboards/Widgets/Widget.tsx +++ b/src/qqq/pages/dashboards/Widgets/Widget.tsx @@ -155,7 +155,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element { const dropdown = component as Dropdown return ( - + - +