diff --git a/src/qqq/components/widgets/Widget.tsx b/src/qqq/components/widgets/Widget.tsx
index da59312..66e749d 100644
--- a/src/qqq/components/widgets/Widget.tsx
+++ b/src/qqq/components/widgets/Widget.tsx
@@ -30,7 +30,7 @@ import Tooltip from "@mui/material/Tooltip/Tooltip";
import Typography from "@mui/material/Typography";
import parse from "html-react-parser";
import React, {useEffect, useState} from "react";
-import {Link, NavigateFunction, useNavigate} from "react-router-dom";
+import {NavigateFunction, useNavigate} from "react-router-dom";
import colors from "qqq/components/legacy/colors";
import DropdownMenu, {DropdownOption} from "qqq/components/widgets/components/DropdownMenu";
@@ -46,6 +46,7 @@ export interface WidgetData
dropdownNeedsSelectedText?: string;
hasPermission?: boolean;
errorLoading?: boolean;
+
[other: string]: any;
}
@@ -53,6 +54,7 @@ export interface WidgetData
interface Props
{
labelAdditionalComponentsLeft: LabelComponent[];
+ labelAdditionalElementsLeft: JSX.Element[];
labelAdditionalComponentsRight: LabelComponent[];
widgetMetaData?: QWidgetMetaData;
widgetData?: WidgetData;
@@ -70,6 +72,7 @@ Widget.defaultProps = {
widgetMetaData: {},
widgetData: {},
labelAdditionalComponentsLeft: [],
+ labelAdditionalElementsLeft: [],
labelAdditionalComponentsRight: [],
};
@@ -88,34 +91,8 @@ export class LabelComponent
{
render = (args: LabelComponentRenderArgs): JSX.Element =>
{
- return (
Unsupported component type
)
- }
-}
-
-
-/*******************************************************************************
- **
- *******************************************************************************/
-export class HeaderLink extends LabelComponent
-{
- label: string;
- to: string
-
- constructor(label: string, to: string)
- {
- super();
- this.label = label;
- this.to = to;
- }
-
- render = (args: LabelComponentRenderArgs): JSX.Element =>
- {
- return (
-
- {this.to ? {this.label} : null}
-
- );
- }
+ return (Unsupported component type
);
+ };
}
@@ -141,8 +118,8 @@ export class AddNewRecordButton extends LabelComponent
openEditForm = (navigate: any, table: QTableMetaData, id: any = null, defaultValues: any, disabledFields: any) =>
{
- navigate(`#/createChild=${table.name}/defaultValues=${JSON.stringify(defaultValues)}/disabledFields=${JSON.stringify(disabledFields)}`)
- }
+ navigate(`#/createChild=${table.name}/defaultValues=${JSON.stringify(defaultValues)}/disabledFields=${JSON.stringify(disabledFields)}`);
+ };
render = (args: LabelComponentRenderArgs): JSX.Element =>
{
@@ -151,35 +128,7 @@ export class AddNewRecordButton extends LabelComponent
);
- }
-}
-
-
-/*******************************************************************************
- **
- *******************************************************************************/
-export class ExportDataButton extends LabelComponent
-{
- callbackToExport: any;
- tooltipTitle: string;
- isDisabled: boolean;
-
- constructor(callbackToExport: any, isDisabled = false, tooltipTitle: string = "Export")
- {
- super();
- this.callbackToExport = callbackToExport;
- this.isDisabled = isDisabled;
- this.tooltipTitle = tooltipTitle;
- }
-
- render = (args: LabelComponentRenderArgs): JSX.Element =>
- {
- return (
-
-
-
- );
- }
+ };
}
@@ -227,7 +176,7 @@ export class Dropdown extends LabelComponent
/>
);
- }
+ };
}
@@ -251,7 +200,7 @@ export class ReloadControl extends LabelComponent
);
- }
+ };
}
@@ -372,7 +321,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element
if (index < 0)
{
- throw(`Could not find table name for label ${tableName}`);
+ throw (`Could not find table name for label ${tableName}`);
}
dropdownData[index] = (changedData) ? changedData.id : null;
@@ -394,7 +343,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element
}
}
- reloadWidget(dropdownData)
+ reloadWidget(dropdownData);
}
}
@@ -422,7 +371,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element
{
console.log(`No reload widget callback in ${props.widgetMetaData.label}`);
}
- }
+ };
const toggleFullScreenWidget = () =>
{
@@ -434,14 +383,14 @@ function Widget(props: React.PropsWithChildren): JSX.Element
{
setFullScreenWidgetClassName("fullScreenWidget");
}
- }
+ };
const hasPermission = props.widgetData?.hasPermission === undefined || props.widgetData?.hasPermission === true;
const isSet = (v: any): boolean =>
{
return (v !== null && v !== undefined);
- }
+ };
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// to avoid taking up the space of the Box with the label and icon and label-components (since it has a height), only output that box if we need any of the components //
@@ -450,6 +399,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element
if (hasPermission)
{
needLabelBox ||= (labelComponentsLeft && labelComponentsLeft.length > 0);
+ needLabelBox ||= (props.labelAdditionalElementsLeft && props.labelAdditionalElementsLeft.length > 0);
needLabelBox ||= (labelComponentsRight && labelComponentsRight.length > 0);
needLabelBox ||= isSet(props.widgetMetaData?.icon);
needLabelBox ||= isSet(props.widgetData?.label);
@@ -530,6 +480,7 @@ function Widget(props: React.PropsWithChildren): JSX.Element
})
)
}
+ {props.labelAdditionalElementsLeft}
{
diff --git a/src/qqq/components/widgets/misc/RecordGridWidget.tsx b/src/qqq/components/widgets/misc/RecordGridWidget.tsx
index 6f02ba8..1f97113 100644
--- a/src/qqq/components/widgets/misc/RecordGridWidget.tsx
+++ b/src/qqq/components/widgets/misc/RecordGridWidget.tsx
@@ -22,10 +22,14 @@
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
+import Button from "@mui/material/Button";
+import Icon from "@mui/material/Icon";
+import Tooltip from "@mui/material/Tooltip/Tooltip";
+import Typography from "@mui/material/Typography";
import {DataGridPro, GridCallbackDetails, GridRowParams, MuiEvent} from "@mui/x-data-grid-pro";
import React, {useEffect, useState} from "react";
-import {useNavigate} from "react-router-dom";
-import Widget, {AddNewRecordButton, ExportDataButton, HeaderLink, LabelComponent} from "qqq/components/widgets/Widget";
+import {useNavigate, Link} from "react-router-dom";
+import Widget, {AddNewRecordButton, LabelComponent} from "qqq/components/widgets/Widget";
import DataGridUtils from "qqq/utils/DataGridUtils";
import HtmlUtils from "qqq/utils/HtmlUtils";
import Client from "qqq/utils/qqq/Client";
@@ -47,6 +51,8 @@ function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
const [records, setRecords] = useState([] as QRecord[])
const [columns, setColumns] = useState([]);
const [allColumns, setAllColumns] = useState([])
+ const [csv, setCsv] = useState(null as string);
+ const [fileName, setFileName] = useState(null as string);
const navigate = useNavigate();
useEffect(() =>
@@ -75,6 +81,7 @@ function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// capture all-columns to use for the export (before we might splice some away from the on-screen display) //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ const allColumns = [... columns];
setAllColumns(JSON.parse(JSON.stringify(columns)));
////////////////////////////////////////////////////////////////
@@ -95,39 +102,42 @@ function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
setRows(rows);
setRecords(records)
setColumns(columns);
- }
- }, [data]);
- const exportCallback = () =>
- {
- let csv = "";
- for (let i = 0; i < allColumns.length; i++)
- {
- csv += `${i > 0 ? "," : ""}"${ValueUtils.cleanForCsv(allColumns[i].headerName)}"`
- }
- csv += "\n";
-
- for (let i = 0; i < records.length; i++)
- {
- for (let j = 0; j < allColumns.length; j++)
+ let csv = "";
+ for (let i = 0; i < allColumns.length; i++)
{
- const value = records[i].displayValues.get(allColumns[j].field) ?? records[i].values.get(allColumns[j].field)
- csv += `${j > 0 ? "," : ""}"${ValueUtils.cleanForCsv(value)}"`
+ csv += `${i > 0 ? "," : ""}"${ValueUtils.cleanForCsv(allColumns[i].headerName)}"`
}
csv += "\n";
- }
- const fileName = (data?.label ?? widgetMetaData.label) + " " + ValueUtils.formatDateTimeForFileName(new Date()) + ".csv";
- HtmlUtils.download(fileName, csv);
- }
+ for (let i = 0; i < records.length; i++)
+ {
+ for (let j = 0; j < allColumns.length; j++)
+ {
+ const value = records[i].displayValues.get(allColumns[j].field) ?? records[i].values.get(allColumns[j].field)
+ csv += `${j > 0 ? "," : ""}"${ValueUtils.cleanForCsv(value)}"`
+ }
+ csv += "\n";
+ }
+
+ const fileName = (data?.label ?? widgetMetaData.label) + " " + ValueUtils.formatDateTimeForFileName(new Date()) + ".csv";
+
+ setCsv(csv);
+ setFileName(fileName);
+ }
+ }, [data]);
///////////////////
// view all link //
///////////////////
- const labelAdditionalComponentsLeft: LabelComponent[] = []
+ const labelAdditionalElementsLeft: JSX.Element[] = [];
if(data && data.viewAllLink)
{
- labelAdditionalComponentsLeft.push(new HeaderLink("View All", data.viewAllLink));
+ labelAdditionalElementsLeft.push(
+
+ View All
+
+ )
}
///////////////////
@@ -149,7 +159,26 @@ function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
}
}
- labelAdditionalComponentsLeft.push(new ExportDataButton(() => exportCallback(), isExportDisabled, tooltipTitle))
+ const onExportClick = () =>
+ {
+ if(csv)
+ {
+ HtmlUtils.download(fileName, csv);
+ }
+ else
+ {
+ alert("There is no data available to export.")
+ }
+ }
+
+ if(widgetMetaData?.showExportButton)
+ {
+ labelAdditionalElementsLeft.push(
+
+
+
+ );
+ }
////////////////////
// add new button //
@@ -184,7 +213,7 @@ function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
- {
if (props.widgetData && rows && columns)
{
- console.log(props.widgetData);
-
let csv = "";
for (let j = 0; j < columns.length; j++)
{
@@ -98,16 +98,37 @@ function TableWidget(props: Props): JSX.Element
csv += "\n";
}
- console.log(csv);
+ setCsv(csv);
const fileName = (props.widgetData.label ?? props.widgetMetaData.label) + " " + ValueUtils.formatDateTimeForFileName(new Date()) + ".csv";
+ setFileName(fileName)
+
+ console.log(`useEffect, setting fileName ${fileName}`);
+ }
+
+ }, [props.widgetMetaData, props.widgetData]);
+
+ const onExportClick = () =>
+ {
+ if(csv)
+ {
HtmlUtils.download(fileName, csv);
}
else
{
- alert("There is no data available to export.");
+ alert("There is no data available to export.")
}
- };
+ }
+
+ const labelAdditionalElementsLeft: JSX.Element[] = [];
+ if(props.widgetMetaData?.showExportButton)
+ {
+ labelAdditionalElementsLeft.push(
+
+
+
+ );
+ }
return (
props.reloadWidgetCallback(data)}
footerHTML={props.widgetData?.footerHTML}
isChild={props.isChild}
- labelAdditionalComponentsLeft={props.widgetMetaData?.showExportButton ? [new ExportDataButton(() => exportCallback(), isExportDisabled)] : []}
+ labelAdditionalElementsLeft={labelAdditionalElementsLeft}
>