Files
qqq-frontend-material-dashb…/src/qqq/components/query/AdvancedQueryPreview.tsx
Darin Kelkhoff eafd8d98cd CE-1115 pre-QA commit on saved report UI, including:
- redo pivots so editing is in a modal
- add form validations
- field rules for clearing one field when another changes
2024-04-14 20:10:29 -05:00

154 lines
6.2 KiB
TypeScript

/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2024. 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 {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
import Box from "@mui/material/Box";
import colors from "qqq/assets/theme/base/colors";
import {validateCriteria} from "qqq/components/query/FilterCriteriaRow";
import XIcon from "qqq/components/query/XIcon";
import FilterUtils from "qqq/utils/qqq/FilterUtils";
import React, {useState} from "react";
interface AdvancedQueryPreviewProps
{
tableMetaData: QTableMetaData;
queryFilter: QQueryFilter;
isEditable: boolean;
isQueryTooComplex: boolean;
removeCriteriaByIndexCallback: (index: number) => void;
}
/*******************************************************************************
** Box shown on query screen (and more??) to preview what a query looks like,
** as an "advanced" style/precursor-to-writing-your-own-query thing.
*******************************************************************************/
export default function AdvancedQueryPreview({tableMetaData, queryFilter, isEditable, isQueryTooComplex, removeCriteriaByIndexCallback}: AdvancedQueryPreviewProps): JSX.Element
{
const [mouseOverElement, setMouseOverElement] = useState(null as string);
/*******************************************************************************
**
*******************************************************************************/
function handleMouseOverElement(name: string)
{
setMouseOverElement(name);
}
/*******************************************************************************
**
*******************************************************************************/
function handleMouseOutElement()
{
setMouseOverElement(null);
}
/*******************************************************************************
** format the current query as a string for showing on-screen as a preview.
*******************************************************************************/
const queryToAdvancedString = (thisQueryFilter: QQueryFilter) =>
{
if (queryFilter == null || !queryFilter.criteria)
{
return (<span></span>);
}
let counter = 0;
return (
<React.Fragment>
{thisQueryFilter.criteria?.map((criteria, i) =>
{
const {criteriaIsValid} = validateCriteria(criteria, null);
if (criteriaIsValid)
{
counter++;
return (
<span key={i} style={{marginBottom: "0.125rem"}} onMouseOver={() => handleMouseOverElement(`queryPreview-${i}`)} onMouseOut={() => handleMouseOutElement()}>
{counter > 1 ? <span style={{marginLeft: "0.25rem", marginRight: "0.25rem"}}>{thisQueryFilter.booleanOperator}&nbsp;</span> : <span />}
{FilterUtils.criteriaToHumanString(tableMetaData, criteria, true)}
{isEditable && !isQueryTooComplex && (
mouseOverElement == `queryPreview-${i}` && <span className={`advancedQueryPreviewX-${counter - 1}`}>
<XIcon position="forAdvancedQueryPreview" onClick={() => removeCriteriaByIndexCallback(i)} /></span>
)}
{counter > 1 && i == thisQueryFilter.criteria?.length - 1 && thisQueryFilter.subFilters?.length > 0 ? <span style={{marginLeft: "0.25rem", marginRight: "0.25rem"}}>{thisQueryFilter.booleanOperator}&nbsp;</span> : <span />}
</span>
);
}
else
{
return (<span />);
}
})}
{thisQueryFilter.subFilters?.length > 0 && (thisQueryFilter.subFilters.map((filter: QQueryFilter, j) =>
{
return (
<React.Fragment key={j}>
{j > 0 ? <span style={{marginLeft: "0.25rem", marginRight: "0.25rem"}}>{thisQueryFilter.booleanOperator}&nbsp;</span> : <span></span>}
<span style={{display: "flex", marginRight: "0.20rem"}}>(</span>
{queryToAdvancedString(filter)}
<span style={{display: "flex", marginRight: "0.20rem"}}>)</span>
</React.Fragment>
);
}))}
</React.Fragment>
);
};
const moreSX = isEditable ?
{
borderTop: `1px solid ${colors.grayLines.main}`,
boxShadow: "inset 0px 0px 4px 2px #EFEFED",
borderRadius: "0 0 0.75rem 0.75rem",
} :
{
borderRadius: "0.75rem",
border: `1px solid ${colors.grayLines.main}`,
}
return (
<Box whiteSpace="nowrap" display="flex" flexShrink={1} flexGrow={1} alignItems="center">
{
<Box
className="advancedQueryString"
display="inline-block"
width="100%"
sx={{fontSize: "1rem", background: "#FFFFFF"}}
minHeight={"2.5rem"}
p={"0.5rem"}
pb={"0.125rem"}
{...moreSX}
>
<Box display="flex" flexWrap="wrap" fontSize="0.875rem">
{queryToAdvancedString(queryFilter)}
</Box>
</Box>
}
</Box>
)
}