mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Merge pull request #60 from Kingsrook/feature/CE-1240-out-of-stock-summary-page
Feature/ce 1240 out of stock summary page
This commit is contained in:
18673
package-lock.json
generated
18673
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -22,16 +22,16 @@
|
|||||||
|
|
||||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import {Box, Skeleton} from "@mui/material";
|
import {Box, Skeleton} from "@mui/material";
|
||||||
import React from "react";
|
|
||||||
import {BlockData} from "qqq/components/widgets/blocks/BlockModels";
|
import {BlockData} from "qqq/components/widgets/blocks/BlockModels";
|
||||||
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
interface CompositeData
|
interface CompositeData
|
||||||
{
|
{
|
||||||
blocks: BlockData[];
|
blocks: BlockData[];
|
||||||
styleOverrides?: any;
|
styleOverrides?: any;
|
||||||
layout?: string
|
layout?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +57,14 @@ export default function CompositeWidget({widgetMetaData, data}: CompositeWidgetP
|
|||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
let layout = data?.layout;
|
let layout = data?.layout;
|
||||||
let boxStyle: any = {};
|
let boxStyle: any = {};
|
||||||
if (layout == "FLEX_ROW_WRAPPED")
|
if (layout == "FLEX_COLUMN")
|
||||||
|
{
|
||||||
|
boxStyle.display = "flex";
|
||||||
|
boxStyle.flexDirection = "column";
|
||||||
|
boxStyle.flexWrap = "wrap";
|
||||||
|
boxStyle.gap = "0.5rem";
|
||||||
|
}
|
||||||
|
else if (layout == "FLEX_ROW_WRAPPED")
|
||||||
{
|
{
|
||||||
boxStyle.display = "flex";
|
boxStyle.display = "flex";
|
||||||
boxStyle.flexDirection = "row";
|
boxStyle.flexDirection = "row";
|
||||||
@ -68,7 +75,7 @@ export default function CompositeWidget({widgetMetaData, data}: CompositeWidgetP
|
|||||||
{
|
{
|
||||||
boxStyle.display = "flex";
|
boxStyle.display = "flex";
|
||||||
boxStyle.flexDirection = "row";
|
boxStyle.flexDirection = "row";
|
||||||
boxStyle.justifyContent = "space-between"
|
boxStyle.justifyContent = "space-between";
|
||||||
boxStyle.gap = "0.25rem";
|
boxStyle.gap = "0.25rem";
|
||||||
}
|
}
|
||||||
else if (layout == "TABLE_SUB_ROW_DETAILS")
|
else if (layout == "TABLE_SUB_ROW_DETAILS")
|
||||||
|
@ -50,7 +50,7 @@ import USMapWidget from "qqq/components/widgets/misc/USMapWidget";
|
|||||||
import ParentWidget from "qqq/components/widgets/ParentWidget";
|
import ParentWidget from "qqq/components/widgets/ParentWidget";
|
||||||
import MultiStatisticsCard from "qqq/components/widgets/statistics/MultiStatisticsCard";
|
import MultiStatisticsCard from "qqq/components/widgets/statistics/MultiStatisticsCard";
|
||||||
import StatisticsCard from "qqq/components/widgets/statistics/StatisticsCard";
|
import StatisticsCard from "qqq/components/widgets/statistics/StatisticsCard";
|
||||||
import Widget, {HeaderIcon, LabelComponent, WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT} from "qqq/components/widgets/Widget";
|
import Widget, {HeaderIcon, LabelComponent, WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT, WidgetData} from "qqq/components/widgets/Widget";
|
||||||
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
||||||
import ProcessRun from "qqq/pages/processes/ProcessRun";
|
import ProcessRun from "qqq/pages/processes/ProcessRun";
|
||||||
import Client from "qqq/utils/qqq/Client";
|
import Client from "qqq/utils/qqq/Client";
|
||||||
@ -293,7 +293,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={`${widgetMetaData.name}-${i}`} sx={{alignItems: "stretch", flexGrow: 1, display: "flex", marginTop: "0px", paddingTop: "0px", width: "100%", height: "100%"}}>
|
<Box key={`${widgetMetaData.name}-${i}`} sx={{alignItems: "stretch", flexGrow: 1, display: "flex", marginTop: "0px", paddingTop: "0px", width: "100%", height: "100%", flexDirection: widgetMetaData.type == "multiTable" ? "column" : "row"}}>
|
||||||
{
|
{
|
||||||
haveLoadedParams && widgetMetaData.type === "parentWidget" && (
|
haveLoadedParams && widgetMetaData.type === "parentWidget" && (
|
||||||
<ParentWidget
|
<ParentWidget
|
||||||
@ -343,6 +343,20 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
widgetMetaData.type === "multiTable" && (
|
||||||
|
widgetData[i]?.tableDataList?.map((tableData: WidgetData, index: number) =>
|
||||||
|
<Box pb={3} key={`${widgetMetaData.type}-${index}`}>
|
||||||
|
<TableWidget
|
||||||
|
widgetMetaData={widgetMetaData}
|
||||||
|
widgetData={tableData}
|
||||||
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
||||||
|
isChild={areChildren}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "stackedBarChart" && (
|
widgetMetaData.type === "stackedBarChart" && (
|
||||||
<Widget
|
<Widget
|
||||||
@ -587,14 +601,16 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
widgetMetaData.type === "reportSetup" && (
|
widgetMetaData.type === "reportSetup" && (
|
||||||
widgetData && widgetData[i] && widgetData[i].queryParams &&
|
widgetData && widgetData[i] && widgetData[i].queryParams &&
|
||||||
<ReportSetupWidget isEditable={false} widgetMetaData={widgetMetaData} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
|
<ReportSetupWidget isEditable={false} widgetMetaData={widgetMetaData} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
|
||||||
{}} />
|
{
|
||||||
|
}} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "pivotTableSetup" && (
|
widgetMetaData.type === "pivotTableSetup" && (
|
||||||
widgetData && widgetData[i] && widgetData[i].queryParams &&
|
widgetData && widgetData[i] && widgetData[i].queryParams &&
|
||||||
<PivotTableSetupWidget isEditable={false} widgetMetaData={widgetMetaData} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
|
<PivotTableSetupWidget isEditable={false} widgetMetaData={widgetMetaData} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
|
||||||
{}} />
|
{
|
||||||
|
}} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -21,14 +21,16 @@
|
|||||||
|
|
||||||
|
|
||||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Icon from "@mui/material/Icon";
|
import Icon from "@mui/material/Icon";
|
||||||
import Tooltip from "@mui/material/Tooltip/Tooltip";
|
import Tooltip from "@mui/material/Tooltip/Tooltip";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import React from "react";
|
|
||||||
import colors from "qqq/assets/theme/base/colors";
|
import colors from "qqq/assets/theme/base/colors";
|
||||||
import {WidgetData} from "qqq/components/widgets/Widget";
|
import {WidgetData} from "qqq/components/widgets/Widget";
|
||||||
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
||||||
|
import React from "react";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Utility class used by Widgets
|
** Utility class used by Widgets
|
||||||
@ -51,6 +53,17 @@ export class WidgetUtils
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static generateLabelLink = (linkText: string, linkURL: string): JSX.Element =>
|
||||||
|
{
|
||||||
|
return (<Box key={1} fontSize="1rem" pl={1} display="inline" position="relative">
|
||||||
|
(<Link to={linkURL}>{linkText}</Link>)
|
||||||
|
</Box>);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -41,7 +41,7 @@ export default function NumberIconBadgeBlock({widgetMetaData, data}: StandardBlo
|
|||||||
{
|
{
|
||||||
data.values.iconName &&
|
data.values.iconName &&
|
||||||
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="icon">
|
<BlockElementWrapper metaData={widgetMetaData} data={data} slot="icon">
|
||||||
<Icon style={{color: data.styles.color, fontSize: "1rem", position: "relative", top: "3px"}}>{data.values.iconName}</Icon>
|
<Icon style={{color: data.styles.color, fontSize: "1rem", marginLeft: "2px", position: "relative", top: "4px"}}>{data.values.iconName}</Icon>
|
||||||
</BlockElementWrapper>
|
</BlockElementWrapper>
|
||||||
}
|
}
|
||||||
</div>);
|
</div>);
|
||||||
|
@ -30,8 +30,6 @@ import TableContainer from "@mui/material/TableContainer";
|
|||||||
import TableRow from "@mui/material/TableRow";
|
import TableRow from "@mui/material/TableRow";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import parse from "html-react-parser";
|
import parse from "html-react-parser";
|
||||||
import React, {useEffect, useMemo, useState} from "react";
|
|
||||||
import {useAsyncDebounce, useExpanded, useGlobalFilter, usePagination, useSortBy, useTable} from "react-table";
|
|
||||||
import colors from "qqq/assets/theme/base/colors";
|
import colors from "qqq/assets/theme/base/colors";
|
||||||
import MDInput from "qqq/components/legacy/MDInput";
|
import MDInput from "qqq/components/legacy/MDInput";
|
||||||
import MDPagination from "qqq/components/legacy/MDPagination";
|
import MDPagination from "qqq/components/legacy/MDPagination";
|
||||||
@ -43,6 +41,8 @@ import DefaultCell from "qqq/components/widgets/tables/cells/DefaultCell";
|
|||||||
import ImageCell from "qqq/components/widgets/tables/cells/ImageCell";
|
import ImageCell from "qqq/components/widgets/tables/cells/ImageCell";
|
||||||
import {TableDataInput} from "qqq/components/widgets/tables/TableCard";
|
import {TableDataInput} from "qqq/components/widgets/tables/TableCard";
|
||||||
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
import WidgetBlock from "qqq/components/widgets/WidgetBlock";
|
||||||
|
import React, {useEffect, useMemo, useState} from "react";
|
||||||
|
import {useAsyncDebounce, useExpanded, useGlobalFilter, usePagination, useSortBy, useTable} from "react-table";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
@ -327,7 +327,7 @@ function DataTable({
|
|||||||
includeHead && (
|
includeHead && (
|
||||||
<Box component="thead" sx={{position: "sticky", top: 0, background: "white", zIndex: 10}}>
|
<Box component="thead" sx={{position: "sticky", top: 0, background: "white", zIndex: 10}}>
|
||||||
{headerGroups.map((headerGroup: any, i: number) => (
|
{headerGroups.map((headerGroup: any, i: number) => (
|
||||||
<TableRow key={i} {...headerGroup.getHeaderGroupProps()} sx={{display: "grid", gridTemplateColumns: gridTemplateColumns}}>
|
<TableRow key={i} {...headerGroup.getHeaderGroupProps()} sx={{display: "grid", alignItems: "flex-end", gridTemplateColumns: gridTemplateColumns}}>
|
||||||
{headerGroup.headers.map((column: any) => (
|
{headerGroup.headers.map((column: any) => (
|
||||||
column.type !== "hidden" && (
|
column.type !== "hidden" && (
|
||||||
<DataTableHeadCell
|
<DataTableHeadCell
|
||||||
@ -453,7 +453,7 @@ function DataTable({
|
|||||||
|
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box></Box>
|
</Box></Box>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -28,13 +28,13 @@ import TableBody from "@mui/material/TableBody";
|
|||||||
import TableContainer from "@mui/material/TableContainer";
|
import TableContainer from "@mui/material/TableContainer";
|
||||||
import TableRow from "@mui/material/TableRow";
|
import TableRow from "@mui/material/TableRow";
|
||||||
import parse from "html-react-parser";
|
import parse from "html-react-parser";
|
||||||
import React, {useEffect, useState} from "react";
|
|
||||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||||
import DataTableBodyCell from "qqq/components/widgets/tables/cells/DataTableBodyCell";
|
import DataTableBodyCell from "qqq/components/widgets/tables/cells/DataTableBodyCell";
|
||||||
import DataTableHeadCell from "qqq/components/widgets/tables/cells/DataTableHeadCell";
|
import DataTableHeadCell from "qqq/components/widgets/tables/cells/DataTableHeadCell";
|
||||||
import DefaultCell from "qqq/components/widgets/tables/cells/DefaultCell";
|
import DefaultCell from "qqq/components/widgets/tables/cells/DefaultCell";
|
||||||
import DataTable from "qqq/components/widgets/tables/DataTable";
|
import DataTable from "qqq/components/widgets/tables/DataTable";
|
||||||
import Client from "qqq/utils/qqq/Client";
|
import Client from "qqq/utils/qqq/Client";
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -43,7 +43,7 @@ import Client from "qqq/utils/qqq/Client";
|
|||||||
export interface TableDataInput
|
export interface TableDataInput
|
||||||
{
|
{
|
||||||
columns: { [key: string]: any }[];
|
columns: { [key: string]: any }[];
|
||||||
columnHeaderTooltips?: { [columnName: string]: string | JSX.Element }
|
columnHeaderTooltips?: { [columnName: string]: string | JSX.Element };
|
||||||
rows: { [key: string]: any }[];
|
rows: { [key: string]: any }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,7 @@ interface Props
|
|||||||
}
|
}
|
||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
|
|
||||||
function TableCard({noRowsFoundHTML, data, rowsPerPage, hidePaginationDropdown, fixedStickyLastRow, fixedHeight, widgetMetaData}: Props): JSX.Element
|
function TableCard({noRowsFoundHTML, data, rowsPerPage, hidePaginationDropdown, fixedStickyLastRow, fixedHeight, widgetMetaData}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const [qInstance, setQInstance] = useState(null as QInstance);
|
const [qInstance, setQInstance] = useState(null as QInstance);
|
||||||
@ -108,7 +109,7 @@ function TableCard({noRowsFoundHTML, data, rowsPerPage, hidePaginationDropdown,
|
|||||||
<TableContainer sx={{boxShadow: "none"}}>
|
<TableContainer sx={{boxShadow: "none"}}>
|
||||||
<Table>
|
<Table>
|
||||||
<Box component="thead">
|
<Box component="thead">
|
||||||
<TableRow key="header">
|
<TableRow sx={{alignItems: "flex-end"}} key="header">
|
||||||
{Array(8).fill(0).map((_, i) =>
|
{Array(8).fill(0).map((_, i) =>
|
||||||
<DataTableHeadCell key={`head-${i}`} sorted={false} width="auto" align="center">
|
<DataTableHeadCell key={`head-${i}`} sorted={false} width="auto" align="center">
|
||||||
<Skeleton width="100%" />
|
<Skeleton width="100%" />
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {htmlToText} from "html-to-text";
|
import {htmlToText} from "html-to-text";
|
||||||
import React, {useContext, useEffect, useState} from "react";
|
|
||||||
import QContext from "QContext";
|
import QContext from "QContext";
|
||||||
import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent";
|
import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent";
|
||||||
import TableCard from "qqq/components/widgets/tables/TableCard";
|
import TableCard from "qqq/components/widgets/tables/TableCard";
|
||||||
@ -31,6 +30,7 @@ import Widget, {WidgetData} from "qqq/components/widgets/Widget";
|
|||||||
import {WidgetUtils} from "qqq/components/widgets/WidgetUtils";
|
import {WidgetUtils} from "qqq/components/widgets/WidgetUtils";
|
||||||
import HtmlUtils from "qqq/utils/HtmlUtils";
|
import HtmlUtils from "qqq/utils/HtmlUtils";
|
||||||
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
||||||
|
import React, {useContext, useEffect, useState} from "react";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
@ -40,8 +40,7 @@ interface Props
|
|||||||
isChild?: boolean;
|
isChild?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableWidget.defaultProps = {
|
TableWidget.defaultProps = {};
|
||||||
};
|
|
||||||
|
|
||||||
function TableWidget(props: Props): JSX.Element
|
function TableWidget(props: Props): JSX.Element
|
||||||
{
|
{
|
||||||
@ -105,7 +104,7 @@ function TableWidget(props: Props): JSX.Element
|
|||||||
setCsv(csv);
|
setCsv(csv);
|
||||||
|
|
||||||
const fileName = WidgetUtils.makeExportFileName(props.widgetData, props.widgetMetaData);
|
const fileName = WidgetUtils.makeExportFileName(props.widgetData, props.widgetMetaData);
|
||||||
setFileName(fileName)
|
setFileName(fileName);
|
||||||
|
|
||||||
console.log(`useEffect, setting fileName ${fileName}`);
|
console.log(`useEffect, setting fileName ${fileName}`);
|
||||||
}
|
}
|
||||||
@ -126,11 +125,15 @@ function TableWidget(props: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alert("There is no data available to export.")
|
alert("There is no data available to export.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const labelAdditionalElementsLeft: JSX.Element[] = [];
|
const labelAdditionalElementsLeft: JSX.Element[] = [];
|
||||||
|
if (props.widgetData?.linkText && props.widgetData?.linkURL)
|
||||||
|
{
|
||||||
|
labelAdditionalElementsLeft.push(WidgetUtils.generateLabelLink(props.widgetData?.linkText, props.widgetData?.linkURL));
|
||||||
|
}
|
||||||
if (props.widgetMetaData?.showExportButton)
|
if (props.widgetMetaData?.showExportButton)
|
||||||
{
|
{
|
||||||
labelAdditionalElementsLeft.push(WidgetUtils.generateExportButton(onExportClick));
|
labelAdditionalElementsLeft.push(WidgetUtils.generateExportButton(onExportClick));
|
||||||
@ -139,10 +142,10 @@ function TableWidget(props: Props): JSX.Element
|
|||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// look for column-header tooltips from helpContent //
|
// look for column-header tooltips from helpContent //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
const columnHeaderTooltips: {[columnName: string]: JSX.Element} = {}
|
const columnHeaderTooltips: { [columnName: string]: JSX.Element } = {};
|
||||||
for (let column of props.widgetData?.columns ?? [])
|
for (let column of props.widgetData?.columns ?? [])
|
||||||
{
|
{
|
||||||
const helpRoles = ["ALL_SCREENS"]
|
const helpRoles = ["ALL_SCREENS"];
|
||||||
const slotName = `columnHeader=${column.accessor}`;
|
const slotName = `columnHeader=${column.accessor}`;
|
||||||
const showHelp = helpHelpActive || hasHelpContent(props.widgetMetaData?.helpContent?.get(slotName), helpRoles);
|
const showHelp = helpHelpActive || hasHelpContent(props.widgetMetaData?.helpContent?.get(slotName), helpRoles);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user