mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Merge pull request #69 from Kingsrook/feature/CE-1556-ops-overview-enhanced-tooltips
Feature/ce 1556 ops overview enhanced tooltips
This commit is contained in:
@ -22,16 +22,19 @@
|
|||||||
|
|
||||||
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 parse from "html-react-parser";
|
||||||
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";
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
interface CompositeData
|
export interface CompositeData
|
||||||
{
|
{
|
||||||
blocks: BlockData[];
|
blocks: BlockData[];
|
||||||
styleOverrides?: any;
|
styleOverrides?: any;
|
||||||
layout?: string;
|
layout?: string;
|
||||||
|
overlayHtml?: string;
|
||||||
|
overlayStyleOverrides?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -97,13 +100,25 @@ export default function CompositeWidget({widgetMetaData, data}: CompositeWidgetP
|
|||||||
boxStyle.borderRadius = "0.5rem";
|
boxStyle.borderRadius = "0.5rem";
|
||||||
boxStyle.background = "#FFFFFF";
|
boxStyle.background = "#FFFFFF";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.styleOverrides)
|
if (data?.styleOverrides)
|
||||||
{
|
{
|
||||||
boxStyle = {...boxStyle, ...data.styleOverrides};
|
boxStyle = {...boxStyle, ...data.styleOverrides};
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<Box sx={boxStyle} className="compositeWidget">
|
let overlayStyle: any = {};
|
||||||
|
|
||||||
|
if (data?.overlayStyleOverrides)
|
||||||
|
{
|
||||||
|
overlayStyle = {...overlayStyle, ...data.overlayStyleOverrides};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
data?.overlayHtml &&
|
||||||
|
<Box sx={overlayStyle} className="blockWidgetOverlay">{parse(data.overlayHtml)}</Box>
|
||||||
|
}
|
||||||
|
<Box sx={boxStyle} className="compositeWidget">
|
||||||
{
|
{
|
||||||
data.blocks.map((block: BlockData, index) => (
|
data.blocks.map((block: BlockData, index) => (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
@ -111,6 +126,8 @@ export default function CompositeWidget({widgetMetaData, data}: CompositeWidgetP
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</Box>);
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -638,8 +638,28 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
|
|
||||||
if (!omitWrappingGridContainer)
|
if (!omitWrappingGridContainer)
|
||||||
{
|
{
|
||||||
// @ts-ignore
|
const gridProps: {[key: string]: any} = {};
|
||||||
renderedWidget = (<Grid id={widgetMetaData.name} item xxl={widgetMetaData.gridColumns ? widgetMetaData.gridColumns : 12} xs={12} sx={{display: "flex", alignItems: "stretch", scrollMarginTop: "100px"}}>
|
|
||||||
|
for(let size of ["xs", "sm", "md", "lg", "xl", "xxl"])
|
||||||
|
{
|
||||||
|
const key = `gridCols:sizeClass:${size}`
|
||||||
|
if(widgetMetaData?.defaultValues?.has(key))
|
||||||
|
{
|
||||||
|
gridProps[size] = widgetMetaData?.defaultValues.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!gridProps["xxl"])
|
||||||
|
{
|
||||||
|
gridProps["xxl"] = widgetMetaData.gridColumns ? widgetMetaData.gridColumns : 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!gridProps["xs"])
|
||||||
|
{
|
||||||
|
gridProps["xs"] = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderedWidget = (<Grid id={widgetMetaData.name} item {...gridProps} sx={{display: "flex", alignItems: "stretch", scrollMarginTop: "100px"}}>
|
||||||
{renderedWidget}
|
{renderedWidget}
|
||||||
</Grid>);
|
</Grid>);
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,19 @@
|
|||||||
|
|
||||||
|
|
||||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import {Tooltip} from "@mui/material";
|
import {Box, Tooltip} from "@mui/material";
|
||||||
import React, {ReactElement, useContext} from "react";
|
|
||||||
import {Link} from "react-router-dom";
|
|
||||||
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 {BlockData, BlockLink, BlockTooltip} from "qqq/components/widgets/blocks/BlockModels";
|
import {BlockData, BlockLink, BlockTooltip} from "qqq/components/widgets/blocks/BlockModels";
|
||||||
|
import CompositeWidget from "qqq/components/widgets/CompositeWidget";
|
||||||
|
import React, {ReactElement, useContext} from "react";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
interface BlockElementWrapperProps
|
interface BlockElementWrapperProps
|
||||||
{
|
{
|
||||||
data: BlockData;
|
data: BlockData;
|
||||||
metaData: QWidgetMetaData;
|
metaData: QWidgetMetaData;
|
||||||
slot: string
|
slot: string;
|
||||||
linkProps?: any;
|
linkProps?: any;
|
||||||
children: ReactElement;
|
children: ReactElement;
|
||||||
}
|
}
|
||||||
@ -47,16 +48,16 @@ export default function BlockElementWrapper({data, metaData, slot, linkProps, ch
|
|||||||
let link: BlockLink;
|
let link: BlockLink;
|
||||||
let tooltip: BlockTooltip;
|
let tooltip: BlockTooltip;
|
||||||
|
|
||||||
if(slot)
|
if (slot)
|
||||||
{
|
{
|
||||||
link = data.linkMap && data.linkMap[slot.toUpperCase()];
|
link = data.linkMap && data.linkMap[slot.toUpperCase()];
|
||||||
if(!link)
|
if (!link)
|
||||||
{
|
{
|
||||||
link = data.link;
|
link = data.link;
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltip = data.tooltipMap && data.tooltipMap[slot.toUpperCase()];
|
tooltip = data.tooltipMap && data.tooltipMap[slot.toUpperCase()];
|
||||||
if(!tooltip)
|
if (!tooltip)
|
||||||
{
|
{
|
||||||
tooltip = data.tooltip;
|
tooltip = data.tooltip;
|
||||||
}
|
}
|
||||||
@ -67,9 +68,9 @@ export default function BlockElementWrapper({data, metaData, slot, linkProps, ch
|
|||||||
tooltip = data.tooltip;
|
tooltip = data.tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!tooltip)
|
if (!tooltip)
|
||||||
{
|
{
|
||||||
const helpRoles = ["ALL_SCREENS"]
|
const helpRoles = ["ALL_SCREENS"];
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// the full keys in the helpContent table will look like: //
|
// the full keys in the helpContent table will look like: //
|
||||||
@ -80,26 +81,39 @@ export default function BlockElementWrapper({data, metaData, slot, linkProps, ch
|
|||||||
const key = data.blockId ? `${data.blockId},${slot}` : slot;
|
const key = data.blockId ? `${data.blockId},${slot}` : slot;
|
||||||
const showHelp = helpHelpActive || hasHelpContent(metaData?.helpContent?.get(key), helpRoles);
|
const showHelp = helpHelpActive || hasHelpContent(metaData?.helpContent?.get(key), helpRoles);
|
||||||
|
|
||||||
if(showHelp)
|
if (showHelp)
|
||||||
{
|
{
|
||||||
const formattedHelpContent = <HelpContent helpContents={metaData?.helpContent?.get(key)} roles={helpRoles} helpContentKey={`widget:${metaData?.name};slot:${key}`} />;
|
const formattedHelpContent = <HelpContent helpContents={metaData?.helpContent?.get(key)} roles={helpRoles} helpContentKey={`widget:${metaData?.name};slot:${key}`} />;
|
||||||
tooltip = {title: formattedHelpContent, placement: "bottom"}
|
tooltip = {title: formattedHelpContent, placement: "bottom"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rs = children;
|
let rs = children;
|
||||||
|
|
||||||
if(link)
|
if (link && link.href)
|
||||||
{
|
{
|
||||||
rs = <Link to={link.href} target={link.target} style={{color: "#546E7A"}} {...linkProps}>{rs}</Link>
|
rs = <Link to={link.href} target={link.target} style={{color: "#546E7A"}} {...linkProps}>{rs}</Link>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tooltip)
|
if (tooltip)
|
||||||
{
|
{
|
||||||
let placement = tooltip.placement ? tooltip.placement.toLowerCase() : "bottom"
|
let placement = tooltip.placement ? tooltip.placement.toLowerCase() : "bottom";
|
||||||
|
|
||||||
// @ts-ignore - placement possible values
|
// @ts-ignore - placement possible values
|
||||||
rs = <Tooltip title={tooltip.title} placement={placement}>{rs}</Tooltip>
|
if (tooltip.blockData)
|
||||||
|
{
|
||||||
|
// @ts-ignore - special case for composite type block...
|
||||||
|
rs = <Tooltip title={
|
||||||
|
<Box sx={{width: "200px"}}>
|
||||||
|
<CompositeWidget widgetMetaData={metaData} data={tooltip?.blockData} />
|
||||||
|
</Box>
|
||||||
|
}>{rs}</Tooltip>;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// @ts-ignore - placement possible values
|
||||||
|
rs = <Tooltip title={tooltip.title} placement={placement}>{rs}</Tooltip>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rs);
|
return (rs);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
|
import {CompositeData} from "qqq/components/widgets/CompositeWidget";
|
||||||
|
|
||||||
|
|
||||||
export interface BlockData
|
export interface BlockData
|
||||||
@ -29,8 +30,8 @@ export interface BlockData
|
|||||||
|
|
||||||
tooltip?: BlockTooltip;
|
tooltip?: BlockTooltip;
|
||||||
link?: BlockLink;
|
link?: BlockLink;
|
||||||
tooltipMap?: {[slot: string]: BlockTooltip};
|
tooltipMap?: { [slot: string]: BlockTooltip };
|
||||||
linkMap?: {[slot: string]: BlockLink};
|
linkMap?: { [slot: string]: BlockLink };
|
||||||
|
|
||||||
values: any;
|
values: any;
|
||||||
styles?: any;
|
styles?: any;
|
||||||
@ -39,6 +40,7 @@ export interface BlockData
|
|||||||
|
|
||||||
export interface BlockTooltip
|
export interface BlockTooltip
|
||||||
{
|
{
|
||||||
|
blockData?: CompositeData;
|
||||||
title: string | JSX.Element;
|
title: string | JSX.Element;
|
||||||
placement: string;
|
placement: string;
|
||||||
}
|
}
|
||||||
|
@ -787,3 +787,20 @@ input[type="search"]::-webkit-search-results-decoration
|
|||||||
{
|
{
|
||||||
margin: 2rem 1rem;
|
margin: 2rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* default styles for a block widget overlay */
|
||||||
|
.blockWidgetOverlay
|
||||||
|
{
|
||||||
|
font-weight: 400;
|
||||||
|
position: relative;
|
||||||
|
top: 15px;
|
||||||
|
height: 0;
|
||||||
|
display: flex;
|
||||||
|
font-size: 14px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.blockWidgetOverlay a
|
||||||
|
{
|
||||||
|
color: #0062FF !important;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user