From 3d3f7efa1d94cac54965e6375e62220d385c801e Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 15 Feb 2023 16:29:54 -0600 Subject: [PATCH] css changes for audits, pvs filters --- package.json | 4 +- src/qqq/components/audits/AuditBody.tsx | 171 +++++++++++++++++- src/qqq/components/misc/SavedFilters.tsx | 2 +- .../components/widgets/DashboardWidgets.tsx | 4 +- src/qqq/components/widgets/ParentWidget.tsx | 7 +- src/qqq/pages/processes/ProcessRun.tsx | 12 +- .../records/query/GridFilterOperators.tsx | 118 +++++++----- src/qqq/pages/records/query/RecordQuery.tsx | 8 +- src/qqq/styles/qqq-override-styles.css | 5 + 9 files changed, 269 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index e671246..0a1a82b 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "@mui/material": "5.11.1", "@mui/styles": "5.11.1", "@mui/system": "5.11.1", - "@mui/x-data-grid": "5.17.6", - "@mui/x-data-grid-pro": "5.17.6", + "@mui/x-data-grid": "5.17.23", + "@mui/x-data-grid-pro": "5.17.23", "@mui/x-license-pro": "5.12.3", "@react-jvectormap/core": "1.0.1", "@react-jvectormap/unitedstates": "1.0.1", diff --git a/src/qqq/components/audits/AuditBody.tsx b/src/qqq/components/audits/AuditBody.tsx index 73777cc..e26c99f 100644 --- a/src/qqq/components/audits/AuditBody.tsx +++ b/src/qqq/components/audits/AuditBody.tsx @@ -34,7 +34,7 @@ import ToggleButton from "@mui/material/ToggleButton"; import ToggleButtonGroup from "@mui/material/ToggleButtonGroup"; import Tooltip from "@mui/material/Tooltip"; import Typography from "@mui/material/Typography"; -import {useContext, useEffect, useState} from "react"; +import React, {JSXElementConstructor, useContext, useEffect, useState} from "react"; import QContext from "QContext"; import Client from "qqq/utils/qqq/Client"; import ValueUtils from "qqq/utils/qqq/ValueUtils"; @@ -58,10 +58,128 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element const [limit, setLimit] = useState(1000); const [statusString, setStatusString] = useState("Loading audits..."); const [auditsByDate, setAuditsByDate] = useState([] as QRecord[][]); - const [auditDetailMap, setAuditDetailMap] = useState(null as Map) + const [auditDetailMap, setAuditDetailMap] = useState(null as Map) + const [fieldChangeMap, setFieldChangeMap] = useState(null as Map) const [sortDirection, setSortDirection] = useState(localStorage.getItem("audit.sortDirection") === "true"); const {accentColor} = useContext(QContext); + function wrapValue(value: any): JSX.Element + { + return {value} + } + + function wasValue(value: any): JSX.Element + { + return {value} + } + + function getAuditDetailFieldChangeRow(qRecord: QRecord): JSX.Element | null + { + const message = qRecord.values.get("auditDetail.message"); + const fieldName = qRecord.values.get("auditDetail.fieldName"); + const oldValue = qRecord.values.get("auditDetail.oldValue"); + const newValue = qRecord.values.get("auditDetail.newValue"); + if(fieldName && (oldValue !== null || newValue !== null)) + { + const fieldLabel = tableMetaData?.fields?.get(fieldName)?.label ?? fieldName + return ({fieldLabel}{oldValue}{newValue}) + } + return (null); + } + + function getAuditDetailElement(qRecord: QRecord): JSX.Element | null + { + const message = qRecord.values.get("auditDetail.message"); + const fieldName = qRecord.values.get("auditDetail.fieldName"); + const oldValue = qRecord.values.get("auditDetail.oldValue"); + const newValue = qRecord.values.get("auditDetail.newValue"); + if(fieldName && (oldValue !== null || newValue !== null)) + { + const fieldLabel = tableMetaData?.fields?.get(fieldName)?.label ?? fieldName; + if(oldValue !== undefined && newValue !== undefined) + { + return (<>{fieldLabel}: Changed from {(oldValue)} to {(newValue)}); + } + else if(newValue !== undefined) + { + return (<>{fieldLabel}: Set to {(newValue)}); + } + else if(oldValue !== undefined) + { + return (<>{fieldLabel}: Removed value {(oldValue)}); + } + + /* + const fieldLabel = {tableMetaData?.fields?.get(fieldName)?.label ?? fieldName}; + if(oldValue !== undefined && newValue !== undefined) + { + return (<>Changed {fieldLabel} from {wrapValue(oldValue)} to {wrapValue(newValue)}); + } + else if(newValue !== undefined) + { + return (<>Set {fieldLabel} to {wrapValue(newValue)}); + } + else if(oldValue !== undefined) + { + return (<>Removed {fieldLabel} value {wrapValue(oldValue)}); + } + */ + + /* + const fieldLabel = {tableMetaData?.fields?.get(fieldName)?.label ?? fieldName}:; + if(oldValue !== undefined && newValue !== undefined) + { + return (<>{fieldLabel} {wrapValue(newValue)} (was {oldValue})); + } + else if(newValue !== undefined) + { + return (<>{fieldLabel} {wrapValue(newValue)} (was --)); + } + else if(oldValue !== undefined) + { + return (<>{fieldLabel} {wrapValue("--")} (was {oldValue})); + } + */ + + /* + const fieldLabel = {tableMetaData?.fields?.get(fieldName)?.label ?? fieldName}:; + if(oldValue !== undefined && newValue !== undefined) + { + return (<>{fieldLabel} {newValue} {wasValue(`(was ${oldValue})`)}); + } + else if(newValue !== undefined) + { + return (<>{fieldLabel} {newValue} {wasValue("(was --)")}); + } + else if(oldValue !== undefined) + { + return (<>{fieldLabel} -- {wasValue(`(was ${oldValue})`)}); + } + */ + + /* + const fieldLabel = {tableMetaData?.fields?.get(fieldName)?.label ?? fieldName}:; + if(oldValue !== undefined && newValue !== undefined) + { + return (<>{fieldLabel} Changed to {wrapValue(newValue)} (was {oldValue})); + } + else if(newValue !== undefined) + { + return (<>{fieldLabel} Set to {wrapValue(newValue)}); + } + else if(oldValue !== undefined) + { + return (<>{fieldLabel} Removed value (was {oldValue})); + } + */ + } + else if(message) + { + return (<>{message}); + } + return (null); + } + useEffect(() => { (async () => @@ -112,7 +230,8 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element // group the audits by auditId (e.g., this is a list that joined audit & auditDetail, so un-flatten it) // ////////////////////////////////////////////////////////////////////////////////////////////////////////// const unflattenedAudits: QRecord[] = [] - const detailMap: Map = new Map(); + const detailMap: Map = new Map(); + const fieldChangeRowsMap: Map = new Map(); for (let i = 0; i < audits.length; i++) { let id = audits[i].values.get("id"); @@ -121,7 +240,7 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element unflattenedAudits.push(audits[i]); } - let auditDetail = audits[i].values.get("auditDetail.message"); + let auditDetail = getAuditDetailElement(audits[i]); if(auditDetail) { if(!detailMap.has(id)) @@ -131,10 +250,45 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element detailMap.get(id).push(auditDetail) } + + // table version, probably not to commit + let fieldChangeRow = getAuditDetailFieldChangeRow(audits[i]); + if(auditDetail) + { + if(!fieldChangeRowsMap.has(id)) + { + fieldChangeRowsMap.set(id, []); + } + // fieldChangeRowsMap.get(id).push(fieldChangeRow) + } } audits = unflattenedAudits; setAuditDetailMap(detailMap); - console.log(detailMap); + + const fieldChangeMap: Map = new Map(); + for (let i = 0; i < unflattenedAudits.length; i++) + { + let id = unflattenedAudits[i].values.get("id"); + if(fieldChangeRowsMap.has(id) && fieldChangeRowsMap.get(id).length > 0) + { + const fieldChangeTable = ( + + + + + + + + + + {fieldChangeRowsMap.get(id).map((row, key) => {row})} + +
FieldOld ValueNew Value
+ ) + fieldChangeMap.set(id, fieldChangeTable); + } + } + setFieldChangeMap(fieldChangeMap) ////////////////////////////// // group the audits by date // @@ -265,11 +419,11 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element check - + {timestampParts[1]} {timestampParts[2]} {timestampParts[3]}   {audit.displayValues.get("auditUserId")} - + {audit.values.get("message")} @@ -282,6 +436,9 @@ function AuditBody({tableMetaData, recordId, record}: Props): JSX.Element } + { + fieldChangeMap.has(audit.values.get("id")) && fieldChangeMap.get(audit.values.get("id")) + } ); diff --git a/src/qqq/components/misc/SavedFilters.tsx b/src/qqq/components/misc/SavedFilters.tsx index 2f3eee2..810c0a9 100644 --- a/src/qqq/components/misc/SavedFilters.tsx +++ b/src/qqq/components/misc/SavedFilters.tsx @@ -413,7 +413,7 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter, {currentSavedFilter.values.get("label")} { filterIsModified && ( - + ) diff --git a/src/qqq/components/widgets/DashboardWidgets.tsx b/src/qqq/components/widgets/DashboardWidgets.tsx index 28ffe0c..6faf189 100644 --- a/src/qqq/components/widgets/DashboardWidgets.tsx +++ b/src/qqq/components/widgets/DashboardWidgets.tsx @@ -396,9 +396,9 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit { widgetMetaDataList.map((widgetMetaData, i) => ( omitWrappingGridContainer - ? renderWidget(widgetMetaData, i) + ? widgetMetaData && renderWidget(widgetMetaData, i) : - + widgetMetaData && {renderWidget(widgetMetaData, i)} )) diff --git a/src/qqq/components/widgets/ParentWidget.tsx b/src/qqq/components/widgets/ParentWidget.tsx index c0e71ea..48b4c11 100644 --- a/src/qqq/components/widgets/ParentWidget.tsx +++ b/src/qqq/components/widgets/ParentWidget.tsx @@ -97,6 +97,11 @@ function ParentWidget({urlParams, widgetMetaData, widgetIndex, data, reloadWidge reloadWidgetCallback(widgetIndex, data); } + /////////////////////////////////////////////////////////////////////////////////////////// + // if this parent widget is in card form, and its children are too, then we need some px // + /////////////////////////////////////////////////////////////////////////////////////////// + const px = (widgetMetaData && widgetMetaData.isCard && widgets && widgets[0] && widgets[0].isCard) ? 3 : 0; + // @ts-ignore return ( qInstance && data ? ( @@ -106,7 +111,7 @@ function ParentWidget({urlParams, widgetMetaData, widgetIndex, data, reloadWidge storeDropdownSelections={storeDropdownSelections} reloadWidgetCallback={parentReloadWidgetCallback} > - + diff --git a/src/qqq/pages/processes/ProcessRun.tsx b/src/qqq/pages/processes/ProcessRun.tsx index 262a34c..35d9a62 100644 --- a/src/qqq/pages/processes/ProcessRun.tsx +++ b/src/qqq/pages/processes/ProcessRun.tsx @@ -34,7 +34,7 @@ import {QJobRunning} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJob import {QJobStarted} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobStarted"; import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord"; import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter"; -import {Button, CircularProgress, Icon, TablePagination} from "@mui/material"; +import {Alert, Button, CircularProgress, Icon, TablePagination} from "@mui/material"; import Box from "@mui/material/Box"; import Card from "@mui/material/Card"; import Grid from "@mui/material/Grid"; @@ -405,8 +405,16 @@ function ProcessRun({process, defaultProcessValues, isModal, isWidget, isReport, component.type === QComponentType.BULK_EDIT_FORM && ( tableMetaData && localTableSections ? + { + localTableSections.length == 0 && + + There are no editable fields on this table. + + } - + { + localTableSections.length > 0 && + } diff --git a/src/qqq/pages/records/query/GridFilterOperators.tsx b/src/qqq/pages/records/query/GridFilterOperators.tsx index d85a2ee..726aa17 100644 --- a/src/qqq/pages/records/query/GridFilterOperators.tsx +++ b/src/qqq/pages/records/query/GridFilterOperators.tsx @@ -56,7 +56,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr CUSTOM = "Custom", } - const delimiterToCharacterMap: {[key: string]: string} = {}; + const delimiterToCharacterMap: { [key: string]: string } = {}; delimiterToCharacterMap[Delimiter.COMMA] = "[,\n\r]"; delimiterToCharacterMap[Delimiter.TAB] = "[\t,\n,\r]"; @@ -87,14 +87,14 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr { event.target.blur(); setPasteModalIsOpen(true); - } + }; const applyValue = (item: GridFilterItem) => { console.log(`updating grid values: ${JSON.stringify(item.value)}`); setGridFilterItem(item); props.applyValue(item); - } + }; const clearData = () => { @@ -104,7 +104,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr setInputText(""); setDetectedText(""); setCustomDelimiterValue(""); - setPasteModalIsOpen(false) + setPasteModalIsOpen(false); }; const handleCancelClicked = () => @@ -115,21 +115,21 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr const handleSaveClicked = () => { - if(gridFilterItem) + if (gridFilterItem) { //////////////////////////////////////// // if numeric remove any non-numerics // //////////////////////////////////////// let saveData = []; - for(let i=0; i { const buckets = new Map(); - for(let i=0; i highestCount) + if (buckets.has(bucketName) && buckets.get(bucketName) > highestCount) { delimiter = bucketName; highestCount = buckets.get(bucketName); @@ -231,7 +231,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr } setDetectedText(`${delimiter} Detected`); - return(delimiterToCharacterMap[delimiter]); + return (delimiterToCharacterMap[delimiter]); }; useEffect(() => @@ -242,10 +242,10 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr ///////////////////////////////////////////////////////////////////////////// // if no delimiter already set in the state, call function to determine it // ///////////////////////////////////////////////////////////////////////////// - if (! currentDelimiter || currentDelimiter === Delimiter.DETECT_AUTOMATICALLY) + if (!currentDelimiter || currentDelimiter === Delimiter.DETECT_AUTOMATICALLY) { currentDelimiterCharacter = calculateAutomaticDelimiter(inputText); - if(! currentDelimiterCharacter) + if (!currentDelimiterCharacter) { return; } @@ -254,7 +254,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr setDelimiter(Delimiter.DETECT_AUTOMATICALLY); setDelimiterCharacter(currentDelimiterCharacter); } - else if(currentDelimiter === Delimiter.CUSTOM) + else if (currentDelimiter === Delimiter.CUSTOM) { //////////////////////////////////////////////////// // if custom, make sure to split on new lines too // @@ -264,7 +264,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr console.log(`current delimiter is: ${currentDelimiter}, delimiting on: ${currentDelimiterCharacter}`); - let regex = new RegExp(currentDelimiterCharacter) + let regex = new RegExp(currentDelimiterCharacter); let parts = inputText.split(regex); let chipData = [] as string[]; @@ -272,7 +272,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr // if delimiter is empty string, dont split anything // /////////////////////////////////////////////////////// setErrorText(""); - if(currentDelimiterCharacter !== "") + if (currentDelimiterCharacter !== "") { for (let i = 0; i < parts.length; i++) { @@ -284,7 +284,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr /////////////////////////////////////////////////////////// // if numeric, check that first before pushing as a chip // /////////////////////////////////////////////////////////// - if(type === "number" && Number.isNaN(Number(part))) + if (type === "number" && Number.isNaN(Number(part))) { setErrorText("Some values are not numbers"); } @@ -301,7 +301,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr { props && ( - + - {}} + { + }} chipData={chipData} chipType={type} multiline @@ -368,7 +369,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr - + SEPARATOR @@ -390,7 +391,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr ))} - { delimiter === Delimiter.CUSTOM.valueOf() && ( + {delimiter === Delimiter.CUSTOM.valueOf() && ( )} - { inputText && delimiter === Delimiter.DETECT_AUTOMATICALLY.valueOf() && ( + {inputText && delimiter === Delimiter.DETECT_AUTOMATICALLY.valueOf() && ( {detectedText} @@ -436,7 +437,7 @@ function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValuePr onClickHandler={handleCancelClicked} iconName="cancel" disabled={false} /> - + @@ -503,7 +504,7 @@ let endsWith = gridStringOperators.splice(0, 1)[0]; // remove default isany operator // /////////////////////////////////// gridStringOperators.splice(2, 1)[0]; -gridStringOperators = [ equals, stringNotEqualsOperator, contains, stringNotContainsOperator, startsWith, stringNotStartsWithOperator, endsWith, stringNotEndWithOperator, ...gridStringOperators, stringIsAnyOfOperator ]; +gridStringOperators = [equals, stringNotEqualsOperator, contains, stringNotContainsOperator, startsWith, stringNotStartsWithOperator, endsWith, stringNotEndWithOperator, ...gridStringOperators, stringIsAnyOfOperator]; export const QGridStringOperators = gridStringOperators; @@ -517,10 +518,10 @@ function InputNumberInterval(props: GridFilterInputValueProps) const {item, applyValue, focusElementRef = null} = props; const filterTimeout = useRef(); - const [ filterValueState, setFilterValueState ] = useState<[ string, string ]>( + const [filterValueState, setFilterValueState] = useState<[string, string]>( item.value ?? "", ); - const [ applying, setIsApplying ] = useState(false); + const [applying, setIsApplying] = useState(false); useEffect(() => { @@ -532,20 +533,20 @@ function InputNumberInterval(props: GridFilterInputValueProps) useEffect(() => { - const itemValue = item.value ?? [ undefined, undefined ]; + const itemValue = item.value ?? [undefined, undefined]; setFilterValueState(itemValue); - }, [ item.value ]); + }, [item.value]); const updateFilterValue = (lowerBound: string, upperBound: string) => { clearTimeout(filterTimeout.current); - setFilterValueState([ lowerBound, upperBound ]); + setFilterValueState([lowerBound, upperBound]); setIsApplying(true); filterTimeout.current = setTimeout(() => { setIsApplying(false); - applyValue({...item, value: [ lowerBound, upperBound ]}); + applyValue({...item, value: [lowerBound, upperBound]}); }, SUBMIT_FILTER_STROKE_TIME); }; @@ -628,7 +629,7 @@ const numericIsAnyOfOperator: GridFilterOperator = { ////////////////////////////// let gridNumericOperators = getGridNumericOperators(); gridNumericOperators.splice(8, 1)[0]; -export const QGridNumericOperators = [ ...gridNumericOperators, betweenOperator, notBetweenOperator, numericIsAnyOfOperator ]; +export const QGridNumericOperators = [...gridNumericOperators, betweenOperator, notBetweenOperator, numericIsAnyOfOperator]; /////////////////////// // boolean operators // @@ -657,7 +658,7 @@ const booleanNotEmptyOperator: GridFilterOperator = { getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null }; -export const QGridBooleanOperators = [ booleanTrueOperator, booleanFalseOperator, booleanEmptyOperator, booleanNotEmptyOperator ]; +export const QGridBooleanOperators = [booleanTrueOperator, booleanFalseOperator, booleanEmptyOperator, booleanNotEmptyOperator]; /////////////////////////////////////// @@ -671,9 +672,9 @@ function InputPossibleValueSourceSingle(tableName: string, field: QFieldMetaData console.log("Item.value? " + item.value); const filterTimeout = useRef(); - const [ filterValueState, setFilterValueState ] = useState(item.value ?? null); - const [ selectedPossibleValue, setSelectedPossibleValue ] = useState((item.value ?? null) as QPossibleValue); - const [ applying, setIsApplying ] = useState(false); + const [filterValueState, setFilterValueState] = useState(item.value ?? null); + const [selectedPossibleValue, setSelectedPossibleValue] = useState((item.value ?? null) as QPossibleValue); + const [applying, setIsApplying] = useState(false); useEffect(() => { @@ -687,7 +688,7 @@ function InputPossibleValueSourceSingle(tableName: string, field: QFieldMetaData { const itemValue = item.value ?? null; setFilterValueState(itemValue); - }, [ item.value ]); + }, [item.value]); const updateFilterValue = (value: QPossibleValue) => { @@ -742,8 +743,8 @@ function InputPossibleValueSourceMultiple(tableName: string, field: QFieldMetaDa console.log("Item.value? " + item.value); const filterTimeout = useRef(); - const [ selectedPossibleValues, setSelectedPossibleValues ] = useState(item.value as QPossibleValue[]); - const [ applying, setIsApplying ] = useState(false); + const [selectedPossibleValues, setSelectedPossibleValues] = useState(item.value as QPossibleValue[]); + const [applying, setIsApplying] = useState(false); useEffect(() => { @@ -756,7 +757,7 @@ function InputPossibleValueSourceMultiple(tableName: string, field: QFieldMetaDa useEffect(() => { const itemValue = item.value ?? null; - }, [ item.value ]); + }, [item.value]); const updateFilterValue = (value: QPossibleValue) => { @@ -797,6 +798,31 @@ function InputPossibleValueSourceMultiple(tableName: string, field: QFieldMetaDa ); } +const getPvsValueString = (value: GridFilterItem["value"]): string => +{ + console.log("get pvs value", value); + if (value && value.length) + { + let labels = [] as string[]; + for (let i = 0; i < value.length; i++) + { + if(value[i] && value[i].label) + { + labels.push(value[i].label); + } + else + { + labels.push(value); + } + } + return (labels.join(", ")); + } + else if (value && value.label) + { + return (value.label); + } + return (value); +}; ////////////////////////////////// // possible value set operators // @@ -808,34 +834,40 @@ export const buildQGridPvsOperators = (tableName: string, field: QFieldMetaData) label: "is", value: "is", getApplyFilterFn: () => null, + getValueAsString: getPvsValueString, InputComponent: (props: GridFilterInputValueProps) => InputPossibleValueSourceSingle(tableName, field, props) }, { label: "is not", value: "isNot", getApplyFilterFn: () => null, + getValueAsString: getPvsValueString, InputComponent: (props: GridFilterInputValueProps) => InputPossibleValueSourceSingle(tableName, field, props) }, { label: "is any of", value: "isAnyOf", + getValueAsString: getPvsValueString, getApplyFilterFn: () => null, InputComponent: (props: GridFilterInputValueProps) => InputPossibleValueSourceMultiple(tableName, field, props) }, { label: "is none of", value: "isNone", + getValueAsString: getPvsValueString, getApplyFilterFn: () => null, InputComponent: (props: GridFilterInputValueProps) => InputPossibleValueSourceMultiple(tableName, field, props) }, { label: "is empty", value: "isEmpty", + getValueAsString: getPvsValueString, getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null }, { label: "is not empty", value: "isNotEmpty", + getValueAsString: getPvsValueString, getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null } ]); diff --git a/src/qqq/pages/records/query/RecordQuery.tsx b/src/qqq/pages/records/query/RecordQuery.tsx index ade6cc5..58eb69a 100644 --- a/src/qqq/pages/records/query/RecordQuery.tsx +++ b/src/qqq/pages/records/query/RecordQuery.tsx @@ -963,9 +963,9 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element Refresh - +
- + { hasValidFilters && ( @@ -991,8 +991,8 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
) } - - + + diff --git a/src/qqq/styles/qqq-override-styles.css b/src/qqq/styles/qqq-override-styles.css index 587a3ea..68f864b 100644 --- a/src/qqq/styles/qqq-override-styles.css +++ b/src/qqq/styles/qqq-override-styles.css @@ -154,6 +154,11 @@ align-items: flex-end; } +.MuiDataGrid-filterFormValueInput > div +{ + height: auto; +} + /* make filter dropdowns a bit wider, less likely to need to wrap. */ .MuiDataGrid-filterForm .MuiDataGrid-filterFormColumnInput {