mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
- New Composite & Block widget constructs. - Option for a parent widget's label to be the app home page's label - Updates to table-widget handling of fixed footer (to expand and stay fixed) - Option for widgets to have CSV Data that can be exported differently from just the data "in" the widget. -- This included changing the default value for showExportButton from true to false
159 lines
5.0 KiB
TypeScript
159 lines
5.0 KiB
TypeScript
/*
|
|
* QQQ - Low-code Application Framework for Engineers.
|
|
* Copyright (C) 2021-2023. 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
|
// @ts-ignore
|
|
import {htmlToText} from "html-to-text";
|
|
import React, {useEffect, useState} from "react";
|
|
import TableCard from "qqq/components/widgets/tables/TableCard";
|
|
import Widget, {WidgetData} from "qqq/components/widgets/Widget";
|
|
import {WidgetUtils} from "qqq/components/widgets/WidgetUtils";
|
|
import HtmlUtils from "qqq/utils/HtmlUtils";
|
|
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
|
|
|
interface Props
|
|
{
|
|
widgetMetaData?: QWidgetMetaData;
|
|
widgetData?: WidgetData;
|
|
reloadWidgetCallback?: (params: string) => void;
|
|
isChild?: boolean;
|
|
}
|
|
|
|
TableWidget.defaultProps = {
|
|
};
|
|
|
|
function TableWidget(props: Props): JSX.Element
|
|
{
|
|
const [isExportDisabled, setIsExportDisabled] = useState(false); // hmm, would like true here, but it broke...
|
|
const [csv, setCsv] = useState(null as string);
|
|
const [fileName, setFileName] = useState(null as string);
|
|
|
|
const rows = props.widgetData?.rows;
|
|
const columns = props.widgetData?.columns;
|
|
|
|
useEffect(() =>
|
|
{
|
|
let isExportDisabled = true;
|
|
if (props.widgetData && columns && rows && rows.length > 0)
|
|
{
|
|
isExportDisabled = false;
|
|
}
|
|
setIsExportDisabled(isExportDisabled);
|
|
|
|
if (props.widgetData && rows && columns)
|
|
{
|
|
let csv = "";
|
|
for (let j = 0; j < columns.length; j++)
|
|
{
|
|
if (j > 0)
|
|
{
|
|
csv += ",";
|
|
}
|
|
csv += `"${columns[j].header}"`;
|
|
}
|
|
csv += "\n";
|
|
|
|
for (let i = 0; i < rows.length; i++)
|
|
{
|
|
for (let j = 0; j < columns.length; j++)
|
|
{
|
|
if (j > 0)
|
|
{
|
|
csv += ",";
|
|
}
|
|
|
|
const cell = rows[i][columns[j].accessor];
|
|
let text = cell;
|
|
if(columns[j].type != "default")
|
|
{
|
|
text = htmlToText(cell,
|
|
{
|
|
selectors: [
|
|
{selector: "a", format: "inline"},
|
|
{selector: ".MuiIcon-root", format: "skip"},
|
|
{selector: ".button", format: "skip"}
|
|
]
|
|
});
|
|
}
|
|
csv += `"${ValueUtils.cleanForCsv(text)}"`;
|
|
}
|
|
csv += "\n";
|
|
}
|
|
|
|
setCsv(csv);
|
|
|
|
const fileName = WidgetUtils.makeExportFileName(props.widgetData, props.widgetMetaData);
|
|
setFileName(fileName)
|
|
|
|
console.log(`useEffect, setting fileName ${fileName}`);
|
|
}
|
|
|
|
}, [props.widgetMetaData, props.widgetData]);
|
|
|
|
const onExportClick = () =>
|
|
{
|
|
if(props.widgetData?.csvData)
|
|
{
|
|
const csv = WidgetUtils.widgetCsvDataToString(props.widgetData);
|
|
const fileName = WidgetUtils.makeExportFileName(props.widgetData, props.widgetMetaData);
|
|
HtmlUtils.download(fileName, csv);
|
|
}
|
|
else if(csv)
|
|
{
|
|
HtmlUtils.download(fileName, csv);
|
|
}
|
|
else
|
|
{
|
|
alert("There is no data available to export.")
|
|
}
|
|
}
|
|
|
|
const labelAdditionalElementsLeft: JSX.Element[] = [];
|
|
if(props.widgetMetaData?.showExportButton)
|
|
{
|
|
labelAdditionalElementsLeft.push(WidgetUtils.generateExportButton(onExportClick));
|
|
}
|
|
|
|
return (
|
|
<Widget
|
|
widgetMetaData={props.widgetMetaData}
|
|
widgetData={props.widgetData}
|
|
reloadWidgetCallback={(data) => props.reloadWidgetCallback(data)}
|
|
footerHTML={props.widgetData?.footerHTML}
|
|
isChild={props.isChild}
|
|
labelAdditionalElementsLeft={labelAdditionalElementsLeft}
|
|
>
|
|
<TableCard
|
|
noRowsFoundHTML={props.widgetData?.noRowsFoundHTML}
|
|
rowsPerPage={props.widgetData?.rowsPerPage}
|
|
hidePaginationDropdown={props.widgetData?.hidePaginationDropdown}
|
|
fixedStickyLastRow={props.widgetData?.fixedStickyLastRow}
|
|
fixedHeight={props.widgetData?.fixedHeight}
|
|
data={{columns: props.widgetData?.columns, rows: props.widgetData?.rows}}
|
|
widgetMetaData={props.widgetMetaData}
|
|
/>
|
|
</Widget>
|
|
);
|
|
}
|
|
|
|
export default TableWidget;
|