From fc238127a7ce4fccbebfe7917d247293491979e7 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 7 Feb 2024 09:28:33 -0600 Subject: [PATCH 1/2] CE-798 z-index fun to fix sticky-header bleed-through --- src/qqq/components/query/FieldListMenu.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qqq/components/query/FieldListMenu.tsx b/src/qqq/components/query/FieldListMenu.tsx index b277aa2..2436d57 100644 --- a/src/qqq/components/query/FieldListMenu.tsx +++ b/src/qqq/components/query/FieldListMenu.tsx @@ -561,6 +561,14 @@ export default function FieldListMenu({idPrefix, heading, placeholder, tableMeta const textFieldId = `field-list-dropdown-${idPrefix}-textField`; let listItemPadding = isModeToggle ? "0.125rem": "0.5rem"; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // for z-indexes, we set each table header to i+1, then the fields in that table to i (so they go behind it) // + // then we increment i by 2 for the next table (so the next header goes above the previous header) // + // this fixes a thing where, if one table's name wrapped to 2 lines, then when the next table below it would // + // come up, if it was only 1 line, then the second line from the previous one would bleed through. // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + let zIndex = 1; + return ( <> { - hasValidFilters && setShowClearFiltersWarning(true)} /> + hasValidFilters && mouseOverElement == "filterBuilderButton" && setShowClearFiltersWarning(true)} /> } @@ -738,14 +766,15 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo { {queryToAdvancedString()} diff --git a/src/qqq/components/query/FilterCriteriaRow.tsx b/src/qqq/components/query/FilterCriteriaRow.tsx index 2e88ea2..e170d00 100644 --- a/src/qqq/components/query/FilterCriteriaRow.tsx +++ b/src/qqq/components/query/FilterCriteriaRow.tsx @@ -53,7 +53,7 @@ export enum ValueMode PVS_MULTI = "PVS_MULTI", } -const getValueModeRequiredCount = (valueMode: ValueMode): number => +export const getValueModeRequiredCount = (valueMode: ValueMode): number => { switch (valueMode) { diff --git a/src/qqq/components/query/QuickFilter.tsx b/src/qqq/components/query/QuickFilter.tsx index ae88728..f881f56 100644 --- a/src/qqq/components/query/QuickFilter.tsx +++ b/src/qqq/components/query/QuickFilter.tsx @@ -24,18 +24,16 @@ import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QField import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData"; import {QCriteriaOperator} from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator"; import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterCriteria"; -import {Badge, Tooltip} from "@mui/material"; +import {Tooltip} from "@mui/material"; import Autocomplete from "@mui/material/Autocomplete"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; -import Icon from "@mui/material/Icon"; -import IconButton from "@mui/material/IconButton"; import Menu from "@mui/material/Menu"; import TextField from "@mui/material/TextField"; import React, {SyntheticEvent, useContext, useState} from "react"; import QContext from "QContext"; import {QFilterCriteriaWithId} from "qqq/components/query/CustomFilterPanel"; -import {getDefaultCriteriaValue, getOperatorOptions, OperatorOption, validateCriteria} from "qqq/components/query/FilterCriteriaRow"; +import {getDefaultCriteriaValue, getOperatorOptions, getValueModeRequiredCount, OperatorOption, validateCriteria} from "qqq/components/query/FilterCriteriaRow"; import FilterCriteriaRowValues from "qqq/components/query/FilterCriteriaRowValues"; import XIcon from "qqq/components/query/XIcon"; import FilterUtils from "qqq/utils/qqq/FilterUtils"; @@ -71,8 +69,7 @@ export const quickFilterButtonStyles = { border: "1px solid #757575", minWidth: "3.5rem", minHeight: "auto", - padding: "0.375rem 0.625rem", - whiteSpace: "nowrap", + padding: "0.375rem 0.625rem", whiteSpace: "nowrap", marginBottom: "0.5rem" } @@ -149,6 +146,7 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData const [isOpen, setIsOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(null); + const [isMouseOver, setIsMouseOver] = useState(false); const [criteria, setCriteria] = useState(criteriaParamIsCriteria(criteriaParam) ? criteriaParam as QFilterCriteriaWithId : null); const [id, setId] = useState(criteriaParamIsCriteria(criteriaParam) ? (criteriaParam as QFilterCriteriaWithId).id : ++seedId); @@ -156,13 +154,29 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData const [operatorSelectedValue, setOperatorSelectedValue] = useState(getOperatorSelectedValue(operatorOptions, criteria, defaultOperator)); const [operatorInputValue, setOperatorInputValue] = useState(operatorSelectedValue?.label); - const [startIconName, setStartIconName] = useState("filter_alt"); - const {criteriaIsValid, criteriaStatusTooltip} = validateCriteria(criteria, operatorSelectedValue); const {accentColor} = useContext(QContext); + /******************************************************************************* + ** + *******************************************************************************/ + function handleMouseOverElement() + { + setIsMouseOver(true); + } + + + /******************************************************************************* + ** + *******************************************************************************/ + function handleMouseOutElement() + { + setIsMouseOver(false); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // handle a change to the criteria from outside this component (e.g., the prop isn't the same as the state) // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -171,7 +185,6 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData const newCriteria = criteriaParam as QFilterCriteriaWithId; setCriteria(newCriteria); const operatorOption = operatorOptions.filter(o => o.value == newCriteria.operator)[0]; - console.log(`B: setOperatorSelectedValue [${JSON.stringify(operatorOption)}]`); setOperatorSelectedValue(operatorOption); setOperatorInputValue(operatorOption.label); } @@ -202,7 +215,6 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData const operatorOption = operatorOptions.filter(o => o.value == defaultOperator)[0]; const criteria = new QFilterCriteriaWithId(fullFieldName, operatorOption?.value, getDefaultCriteriaValue()); criteria.id = id; - console.log(`C: setOperatorSelectedValue [${JSON.stringify(operatorOption)}]`); setOperatorSelectedValue(operatorOption); setOperatorInputValue(operatorOption?.label); setCriteria(criteria); @@ -216,6 +228,12 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData { setIsOpen(!isOpen); setAnchorEl(event.currentTarget); + + setTimeout(() => + { + const element = document.getElementById("value-" + criteria.id); + element?.focus(); + }) }; /******************************************************************************* @@ -236,7 +254,6 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData if (newValue) { - console.log(`D: setOperatorSelectedValue [${JSON.stringify(newValue)}]`); setOperatorSelectedValue(newValue); setOperatorInputValue(newValue.label); @@ -244,10 +261,27 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData { criteria.values = newValue.implicitValues; } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // we've seen cases where switching operators can sometimes put a null in as the first value... // + // that just causes a bad time (e.g., null pointers in Autocomplete), so, get rid of that. // + ////////////////////////////////////////////////////////////////////////////////////////////////// + if(criteria.values && criteria.values.length == 1 && criteria.values[0] == null) + { + criteria.values = []; + } + + if(newValue.valueMode) + { + const requiredValueCount = getValueModeRequiredCount(newValue.valueMode); + if(requiredValueCount != null && criteria.values.length > requiredValueCount) + { + criteria.values.splice(requiredValueCount); + } + } } else { - console.log("E: setOperatorSelectedValue [null]"); setOperatorSelectedValue(null); setOperatorInputValue(""); } @@ -307,30 +341,9 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData e.stopPropagation(); const newCriteria = makeNewCriteria(); updateCriteria(newCriteria, false, true); - setStartIconName("filter_alt"); } } - /******************************************************************************* - ** event handler for mouse-over on the filter icon - that changes to an 'x' - ** if there's a valid criteria in the quick-filter - *******************************************************************************/ - const startIconMouseOver = () => - { - if(criteriaIsValid) - { - setStartIconName("clear"); - } - } - - /******************************************************************************* - ** event handler for mouse-out on the filter icon - always resets it. - *******************************************************************************/ - const startIconMouseOut = () => - { - setStartIconName("filter_alt"); - } - /******************************************************************************* ** event handler for clicking the (x) icon that turns off this quick filter field. ** hands off control to the function that was passed in (e.g., from RecordQueryOrig). @@ -359,7 +372,6 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData const maybeNewOperatorSelectedValue = getOperatorSelectedValue(operatorOptions, criteria, defaultOperator); if(JSON.stringify(maybeNewOperatorSelectedValue) !== JSON.stringify(operatorSelectedValue)) { - console.log(`A: setOperatorSelectedValue [${JSON.stringify(maybeNewOperatorSelectedValue)}]`); setOperatorSelectedValue(maybeNewOperatorSelectedValue) setOperatorInputValue(maybeNewOperatorSelectedValue?.label) } @@ -377,11 +389,6 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData ///////////////////////// const tooComplex = criteriaParam == "tooComplex"; const tooltipEnterDelay = 500; - let startIcon = {startIconName} - if(criteriaIsValid) - { - startIcon = {startIcon} - } let buttonAdditionalStyles: any = {}; let buttonContent = {tableForField?.name != tableMetaData.name ? `${tableForField.label}: ` : ""}{fieldMetaData.label} @@ -402,16 +409,19 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData valuesString = ""; } - buttonContent = ( - - {buttonContent} - - ); + buttonContent = (<>{buttonContent}: {operatorSelectedValue.label} {valuesString}); } + const mouseEvents = + { + onMouseOver: () => handleMouseOverElement(), + onMouseOut: () => handleMouseOutElement() + }; + let button = fieldMetaData &&