diff --git a/src/qqq/pages/records/query/GridFilterOperators.tsx b/src/qqq/pages/records/query/GridFilterOperators.tsx
deleted file mode 100644
index fbf7a57..0000000
--- a/src/qqq/pages/records/query/GridFilterOperators.tsx
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
- * QQQ - Low-code Application Framework for Engineers.
- * Copyright (C) 2021-2022. 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 .
- */
-
-import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
-import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
-import {FormControl, InputLabel, Select, SelectChangeEvent, TextFieldProps} from "@mui/material";
-import Box from "@mui/material/Box";
-import Card from "@mui/material/Card";
-import Grid from "@mui/material/Grid";
-import Icon from "@mui/material/Icon";
-import Modal from "@mui/material/Modal";
-import TextField from "@mui/material/TextField";
-import Tooltip from "@mui/material/Tooltip";
-import Typography from "@mui/material/Typography";
-import {getGridNumericOperators, getGridStringOperators, GridColDef, GridFilterInputMultipleValue, GridFilterInputMultipleValueProps, GridFilterInputValueProps, GridFilterItem} from "@mui/x-data-grid-pro";
-import {GridFilterInputValue} from "@mui/x-data-grid/components/panel/filterPanel/GridFilterInputValue";
-import {GridApiCommunity} from "@mui/x-data-grid/internals";
-import {GridFilterOperator} from "@mui/x-data-grid/models/gridFilterOperator";
-import React, {useEffect, useRef, useState} from "react";
-import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
-import ChipTextField from "qqq/components/forms/ChipTextField";
-import DynamicSelect from "qqq/components/forms/DynamicSelect";
-
-
-////////////////////////////////
-// input element for 'is any' //
-////////////////////////////////
-function CustomIsAnyInput(type: "number" | "text", props: GridFilterInputValueProps)
-{
- enum Delimiter
- {
- DETECT_AUTOMATICALLY = "Detect Automatically",
- COMMA = "Comma",
- NEWLINE = "Newline",
- PIPE = "Pipe",
- SPACE = "Space",
- TAB = "Tab",
- CUSTOM = "Custom",
- }
-
- const delimiterToCharacterMap: { [key: string]: string } = {};
-
- delimiterToCharacterMap[Delimiter.COMMA] = "[,\n\r]";
- delimiterToCharacterMap[Delimiter.TAB] = "[\t,\n,\r]";
- delimiterToCharacterMap[Delimiter.NEWLINE] = "[\n\r]";
- delimiterToCharacterMap[Delimiter.PIPE] = "[\\|\r\n]";
- delimiterToCharacterMap[Delimiter.SPACE] = "[ \n\r]";
-
- const delimiterDropdownOptions = Object.values(Delimiter);
-
- const mainCardStyles: any = {};
- mainCardStyles.width = "60%";
- mainCardStyles.minWidth = "500px";
-
- const [gridFilterItem, setGridFilterItem] = useState(props.item);
- const [pasteModalIsOpen, setPasteModalIsOpen] = useState(false);
- const [inputText, setInputText] = useState("");
- const [delimiter, setDelimiter] = useState("");
- const [delimiterCharacter, setDelimiterCharacter] = useState("");
- const [customDelimiterValue, setCustomDelimiterValue] = useState("");
- const [chipData, setChipData] = useState(undefined);
- const [detectedText, setDetectedText] = useState("");
- const [errorText, setErrorText] = useState("");
-
- //////////////////////////////////////////////////////////////
- // handler for when paste icon is clicked in 'any' operator //
- //////////////////////////////////////////////////////////////
- const handlePasteClick = (event: any) =>
- {
- 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 = () =>
- {
- setDelimiter("");
- setDelimiterCharacter("");
- setChipData([]);
- setInputText("");
- setDetectedText("");
- setCustomDelimiterValue("");
- setPasteModalIsOpen(false);
- };
-
- const handleCancelClicked = () =>
- {
- clearData();
- setPasteModalIsOpen(false);
- };
-
- const handleSaveClicked = () =>
- {
- if (gridFilterItem)
- {
- ////////////////////////////////////////
- // if numeric remove any non-numerics //
- ////////////////////////////////////////
- let saveData = [];
- for (let i = 0; i < chipData.length; i++)
- {
- if (type !== "number" || !Number.isNaN(Number(chipData[i])))
- {
- saveData.push(chipData[i]);
- }
- }
-
- if (gridFilterItem.value)
- {
- gridFilterItem.value = [...gridFilterItem.value, ...saveData];
- }
- else
- {
- gridFilterItem.value = saveData;
- }
-
- setGridFilterItem(gridFilterItem);
- props.applyValue(gridFilterItem);
- }
-
- clearData();
- setPasteModalIsOpen(false);
- };
-
- ////////////////////////////////////////////////////////////////
- // when user selects a different delimiter on the parse modal //
- ////////////////////////////////////////////////////////////////
- const handleDelimiterChange = (event: SelectChangeEvent) =>
- {
- const newDelimiter = event.target.value;
- console.log(`Delimiter Changed to ${JSON.stringify(newDelimiter)}`);
-
- setDelimiter(newDelimiter);
- if (newDelimiter === Delimiter.CUSTOM)
- {
- setDelimiterCharacter(customDelimiterValue);
- }
- else
- {
- setDelimiterCharacter(delimiterToCharacterMap[newDelimiter]);
- }
- };
-
- const handleTextChange = (event: any) =>
- {
- const inputText = event.target.value;
- setInputText(inputText);
- };
-
- const handleCustomDelimiterChange = (event: any) =>
- {
- let inputText = event.target.value;
- setCustomDelimiterValue(inputText);
- };
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // iterate over each character, putting them into 'buckets' so that we can determine //
- // a good default to use when data is pasted into the textarea //
- ///////////////////////////////////////////////////////////////////////////////////////
- const calculateAutomaticDelimiter = (text: string): string =>
- {
- const buckets = new Map();
- for (let i = 0; i < text.length; i++)
- {
- let bucketName = "";
-
- switch (text.charAt(i))
- {
- case "\t":
- bucketName = Delimiter.TAB;
- break;
- case "\n":
- case "\r":
- bucketName = Delimiter.NEWLINE;
- break;
- case "|":
- bucketName = Delimiter.PIPE;
- break;
- case " ":
- bucketName = Delimiter.SPACE;
- break;
- case ",":
- bucketName = Delimiter.COMMA;
- break;
- }
-
- if (bucketName !== "")
- {
- let currentCount = (buckets.has(bucketName)) ? buckets.get(bucketName) : 0;
- buckets.set(bucketName, currentCount + 1);
- }
- }
-
- ///////////////////////
- // default is commas //
- ///////////////////////
- let highestCount = 0;
- let delimiter = Delimiter.COMMA;
- for (let j = 0; j < delimiterDropdownOptions.length; j++)
- {
- let bucketName = delimiterDropdownOptions[j];
- if (buckets.has(bucketName) && buckets.get(bucketName) > highestCount)
- {
- delimiter = bucketName;
- highestCount = buckets.get(bucketName);
- }
- }
-
- setDetectedText(`${delimiter} Detected`);
- return (delimiterToCharacterMap[delimiter]);
- };
-
- useEffect(() =>
- {
- let currentDelimiter = delimiter;
- let currentDelimiterCharacter = delimiterCharacter;
-
- /////////////////////////////////////////////////////////////////////////////
- // if no delimiter already set in the state, call function to determine it //
- /////////////////////////////////////////////////////////////////////////////
- if (!currentDelimiter || currentDelimiter === Delimiter.DETECT_AUTOMATICALLY)
- {
- currentDelimiterCharacter = calculateAutomaticDelimiter(inputText);
- if (!currentDelimiterCharacter)
- {
- return;
- }
-
- currentDelimiter = Delimiter.DETECT_AUTOMATICALLY;
- setDelimiter(Delimiter.DETECT_AUTOMATICALLY);
- setDelimiterCharacter(currentDelimiterCharacter);
- }
- else if (currentDelimiter === Delimiter.CUSTOM)
- {
- ////////////////////////////////////////////////////
- // if custom, make sure to split on new lines too //
- ////////////////////////////////////////////////////
- currentDelimiterCharacter = `[${customDelimiterValue}\r\n]`;
- }
-
- console.log(`current delimiter is: ${currentDelimiter}, delimiting on: ${currentDelimiterCharacter}`);
-
- let regex = new RegExp(currentDelimiterCharacter);
- let parts = inputText.split(regex);
- let chipData = [] as string[];
-
- ///////////////////////////////////////////////////////
- // if delimiter is empty string, dont split anything //
- ///////////////////////////////////////////////////////
- setErrorText("");
- if (currentDelimiterCharacter !== "")
- {
- for (let i = 0; i < parts.length; i++)
- {
- let part = parts[i].trim();
- if (part !== "")
- {
- chipData.push(part);
-
- ///////////////////////////////////////////////////////////
- // if numeric, check that first before pushing as a chip //
- ///////////////////////////////////////////////////////////
- if (type === "number" && Number.isNaN(Number(part)))
- {
- setErrorText("Some values are not numbers");
- }
- }
- }
- }
-
- setChipData(chipData);
-
- }, [inputText, delimiterCharacter, customDelimiterValue, detectedText]);
-
- return (
-
- {
- props &&
- (
-
-
-
- paste_content
-
-
- )
- }
- {
- pasteModalIsOpen &&
- (
-
-
-
-
-
-
-
- Bulk Add Filter Values
-
- Paste into the box on the left.
- Review the filter values in the box on the right.
- If the filter values are not what are expected, try changing the separator using the dropdown below.
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- }}
- chipData={chipData}
- chipType={type}
- multiline
- fullWidth
- variant="outlined"
- id="tags"
- rows={0}
- name="tags"
- label="FILTER VALUES REVIEW"
- />
-
-
-
-
-
-
-
-
- SEPARATOR
-
-
-
- {delimiter === Delimiter.CUSTOM.valueOf() && (
-
-
-
-
- )}
- {inputText && delimiter === Delimiter.DETECT_AUTOMATICALLY.valueOf() && (
-
-
- {detectedText}
-
- )}
-
-
-
- {
- errorText && chipData.length > 0 && (
-
- error
- {errorText}
-
- )
- }
-
-
- {
- chipData && chipData.length > 0 && (
- {chipData.length.toLocaleString()} {chipData.length === 1 ? "value" : "values"}
- )
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-
- );
-}
-
-//////////////////////
-// string operators //
-//////////////////////
-const stringNotEqualsOperator: GridFilterOperator = {
- label: "does not equal",
- value: "isNot",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: GridFilterInputValue,
-};
-
-const stringNotContainsOperator: GridFilterOperator = {
- label: "does not contain",
- value: "notContains",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: GridFilterInputValue,
-};
-
-const stringNotStartsWithOperator: GridFilterOperator = {
- label: "does not start with",
- value: "notStartsWith",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: GridFilterInputValue,
-};
-
-const stringNotEndWithOperator: GridFilterOperator = {
- label: "does not end with",
- value: "notEndsWith",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: GridFilterInputValue,
-};
-
-const getListValueString = (value: GridFilterItem["value"]): string =>
-{
- if (value && value.length)
- {
- let labels = [] as string[];
-
- let maxLoops = value.length;
- if(maxLoops > 5)
- {
- maxLoops = 3;
- }
-
- for (let i = 0; i < maxLoops; i++)
- {
- labels.push(value[i]);
- }
-
- if(maxLoops < value.length)
- {
- labels.push(" and " + (value.length - maxLoops) + " other values.");
- }
-
- return (labels.join(", "));
- }
- return (value);
-};
-
-const stringIsAnyOfOperator: GridFilterOperator = {
- label: "is any of",
- value: "isAnyOf",
- getValueAsString: getListValueString,
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: (props: GridFilterInputMultipleValueProps) => CustomIsAnyInput("text", props)
-};
-
-const stringIsNoneOfOperator: GridFilterOperator = {
- label: "is none of",
- value: "isNone",
- getValueAsString: getListValueString,
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: (props: GridFilterInputMultipleValueProps) => CustomIsAnyInput("text", props)
-};
-
-let gridStringOperators = getGridStringOperators();
-let equals = gridStringOperators.splice(1, 1)[0];
-let contains = gridStringOperators.splice(0, 1)[0];
-let startsWith = gridStringOperators.splice(0, 1)[0];
-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, stringIsNoneOfOperator];
-
-export const QGridStringOperators = gridStringOperators;
-
-
-///////////////////////////////////////
-// input element for numbers-between //
-///////////////////////////////////////
-function InputNumberInterval(props: GridFilterInputValueProps)
-{
- const SUBMIT_FILTER_STROKE_TIME = 500;
- const {item, applyValue, focusElementRef = null} = props;
-
- const filterTimeout = useRef();
- const [filterValueState, setFilterValueState] = useState<[string, string]>(
- item.value ?? "",
- );
- const [applying, setIsApplying] = useState(false);
-
- useEffect(() =>
- {
- return () =>
- {
- clearTimeout(filterTimeout.current);
- };
- }, []);
-
- useEffect(() =>
- {
- const itemValue = item.value ?? [undefined, undefined];
- setFilterValueState(itemValue);
- }, [item.value]);
-
- const updateFilterValue = (lowerBound: string, upperBound: string) =>
- {
- clearTimeout(filterTimeout.current);
- setFilterValueState([lowerBound, upperBound]);
-
- setIsApplying(true);
- filterTimeout.current = setTimeout(() =>
- {
- setIsApplying(false);
- applyValue({...item, value: [lowerBound, upperBound]});
- }, SUBMIT_FILTER_STROKE_TIME);
- };
-
- const handleUpperFilterChange: TextFieldProps["onChange"] = (event) =>
- {
- const newUpperBound = event.target.value;
- updateFilterValue(filterValueState[0], newUpperBound);
- };
- const handleLowerFilterChange: TextFieldProps["onChange"] = (event) =>
- {
- const newLowerBound = event.target.value;
- updateFilterValue(newLowerBound, filterValueState[1]);
- };
-
- return (
-
-
- sync} : {}}
- />
-
- );
-}
-
-
-//////////////////////
-// number operators //
-//////////////////////
-const betweenOperator: GridFilterOperator = {
- label: "is between",
- value: "between",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: InputNumberInterval
-};
-
-const notBetweenOperator: GridFilterOperator = {
- label: "is not between",
- value: "notBetween",
- getApplyFilterFn: () => null,
- // @ts-ignore
- InputComponent: InputNumberInterval
-};
-
-const numericIsAnyOfOperator: GridFilterOperator = {
- label: "is any of",
- value: "isAnyOf",
- getApplyFilterFn: () => null,
- getValueAsString: getListValueString,
- // @ts-ignore
- InputComponent: (props: GridFilterInputMultipleValueProps) => CustomIsAnyInput("number", props)
-};
-
-const numericIsNoneOfOperator: GridFilterOperator = {
- label: "is none of",
- value: "isNone",
- getApplyFilterFn: () => null,
- getValueAsString: getListValueString,
- // @ts-ignore
- InputComponent: (props: GridFilterInputMultipleValueProps) => CustomIsAnyInput("number", props)
-};
-
-//////////////////////////////
-// remove default is any of //
-//////////////////////////////
-let gridNumericOperators = getGridNumericOperators();
-gridNumericOperators.splice(8, 1)[0];
-export const QGridNumericOperators = [...gridNumericOperators, betweenOperator, notBetweenOperator, numericIsAnyOfOperator, numericIsNoneOfOperator];
-
-///////////////////////
-// boolean operators //
-///////////////////////
-const booleanTrueOperator: GridFilterOperator = {
- label: "is yes",
- value: "isTrue",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-const booleanFalseOperator: GridFilterOperator = {
- label: "is no",
- value: "isFalse",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-const booleanEmptyOperator: GridFilterOperator = {
- label: "is empty",
- value: "isEmpty",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-const booleanNotEmptyOperator: GridFilterOperator = {
- label: "is not empty",
- value: "isNotEmpty",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-export const QGridBooleanOperators = [booleanTrueOperator, booleanFalseOperator, booleanEmptyOperator, booleanNotEmptyOperator];
-
-const blobEmptyOperator: GridFilterOperator = {
- label: "is empty",
- value: "isEmpty",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-const blobNotEmptyOperator: GridFilterOperator = {
- label: "is not empty",
- value: "isNotEmpty",
- getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => null
-};
-
-export const QGridBlobOperators = [blobNotEmptyOperator, blobEmptyOperator];
-
-
-///////////////////////////////////////
-// input element for possible values //
-///////////////////////////////////////
-function InputPossibleValueSourceSingle(tableName: string, field: QFieldMetaData, props: GridFilterInputValueProps)
-{
- const SUBMIT_FILTER_STROKE_TIME = 500;
- const {item, applyValue, focusElementRef = null} = props;
-
- 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);
-
- useEffect(() =>
- {
- return () =>
- {
- clearTimeout(filterTimeout.current);
- };
- }, []);
-
- useEffect(() =>
- {
- const itemValue = item.value ?? null;
- setFilterValueState(itemValue);
- }, [item.value]);
-
- const updateFilterValue = (value: QPossibleValue) =>
- {
- clearTimeout(filterTimeout.current);
- setFilterValueState(value);
-
- setIsApplying(true);
- filterTimeout.current = setTimeout(() =>
- {
- setIsApplying(false);
- applyValue({...item, value: value});
- }, SUBMIT_FILTER_STROKE_TIME);
- };
-
- const handleChange = (value: QPossibleValue) =>
- {
- updateFilterValue(value);
- };
-
- return (
-
- sync} : {}}
- />
-
- );
-}
-
-
-////////////////////////////////////////////////
-// input element for multiple possible values //
-////////////////////////////////////////////////
-function InputPossibleValueSourceMultiple(tableName: string, field: QFieldMetaData, props: GridFilterInputValueProps)
-{
- const SUBMIT_FILTER_STROKE_TIME = 500;
- const {item, applyValue, focusElementRef = null} = props;
-
- console.log("Item.value? " + item.value);
-
- const filterTimeout = useRef();
- const [selectedPossibleValues, setSelectedPossibleValues] = useState(item.value as QPossibleValue[]);
- const [applying, setIsApplying] = useState(false);
-
- useEffect(() =>
- {
- return () =>
- {
- clearTimeout(filterTimeout.current);
- };
- }, []);
-
- useEffect(() =>
- {
- const itemValue = item.value ?? null;
- }, [item.value]);
-
- const updateFilterValue = (value: QPossibleValue) =>
- {
- clearTimeout(filterTimeout.current);
-
- setIsApplying(true);
- filterTimeout.current = setTimeout(() =>
- {
- setIsApplying(false);
- applyValue({...item, value: value});
- }, SUBMIT_FILTER_STROKE_TIME);
- };
-
- const handleChange = (value: QPossibleValue) =>
- {
- updateFilterValue(value);
- };
-
- return (
-
-
-
- );
-}
-
-const getPvsValueString = (value: GridFilterItem["value"]): string =>
-{
- if (value && value.length)
- {
- let labels = [] as string[];
-
- let maxLoops = value.length;
- if(maxLoops > 5)
- {
- maxLoops = 3;
- }
-
- for (let i = 0; i < maxLoops; i++)
- {
- if(value[i] && value[i].label)
- {
- labels.push(value[i].label);
- }
- else
- {
- labels.push(value);
- }
- }
-
- if(maxLoops < value.length)
- {
- labels.push(" and " + (value.length - maxLoops) + " other values.");
- }
-
- return (labels.join(", "));
- }
- else if (value && value.label)
- {
- return (value.label);
- }
- return (value);
-};
-
-//////////////////////////////////
-// possible value set operators //
-//////////////////////////////////
-export const buildQGridPvsOperators = (tableName: string, field: QFieldMetaData): GridFilterOperator[] =>
-{
- return ([
- {
- 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/utils/DataGridUtils.tsx b/src/qqq/utils/DataGridUtils.tsx
index 4cc692f..c5be12a 100644
--- a/src/qqq/utils/DataGridUtils.tsx
+++ b/src/qqq/utils/DataGridUtils.tsx
@@ -26,62 +26,14 @@ import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstan
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
import Tooltip from "@mui/material/Tooltip/Tooltip";
-import {GridColDef, GridFilterItem, GridRowsProp, MuiEvent} from "@mui/x-data-grid-pro";
-import {GridFilterOperator} from "@mui/x-data-grid/models/gridFilterOperator";
+import {GridColDef, GridRowsProp, MuiEvent} from "@mui/x-data-grid-pro";
import {GridColumnHeaderParams} from "@mui/x-data-grid/models/params/gridColumnHeaderParams";
import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent";
-import {buildQGridPvsOperators, QGridBlobOperators, QGridBooleanOperators, QGridNumericOperators, QGridStringOperators} from "qqq/pages/records/query/GridFilterOperators";
import ValueUtils from "qqq/utils/qqq/ValueUtils";
import React from "react";
import {Link, NavigateFunction} from "react-router-dom";
-const emptyApplyFilterFn = (filterItem: GridFilterItem, column: GridColDef): null => null;
-
-function NullInputComponent()
-{
- return ();
-}
-
-const makeGridFilterOperator = (value: string, label: string, takesValues: boolean = false): GridFilterOperator =>
-{
- const rs: GridFilterOperator = {value: value, label: label, getApplyFilterFn: emptyApplyFilterFn};
- if (takesValues)
- {
- rs.InputComponent = NullInputComponent;
- }
- return (rs);
-};
-
-////////////////////////////////////////////////////////////////////////////////////////
-// at this point, these may only be used to drive the toolitp on the FILTER button... //
-////////////////////////////////////////////////////////////////////////////////////////
-const QGridDateOperators = [
- makeGridFilterOperator("equals", "equals", true),
- makeGridFilterOperator("isNot", "does not equal", true),
- makeGridFilterOperator("after", "is after", true),
- makeGridFilterOperator("onOrAfter", "is on or after", true),
- makeGridFilterOperator("before", "is before", true),
- makeGridFilterOperator("onOrBefore", "is on or before", true),
- makeGridFilterOperator("isEmpty", "is empty"),
- makeGridFilterOperator("isNotEmpty", "is not empty"),
- makeGridFilterOperator("between", "is between", true),
- makeGridFilterOperator("notBetween", "is not between", true),
-];
-
-const QGridDateTimeOperators = [
- makeGridFilterOperator("equals", "equals", true),
- makeGridFilterOperator("isNot", "does not equal", true),
- makeGridFilterOperator("after", "is after", true),
- makeGridFilterOperator("onOrAfter", "is at or after", true),
- makeGridFilterOperator("before", "is before", true),
- makeGridFilterOperator("onOrBefore", "is at or before", true),
- makeGridFilterOperator("isEmpty", "is empty"),
- makeGridFilterOperator("isNotEmpty", "is not empty"),
- makeGridFilterOperator("between", "is between", true),
- makeGridFilterOperator("notBetween", "is not between", true),
-];
-
export default class DataGridUtils
{
/*******************************************************************************
@@ -295,11 +247,10 @@ export default class DataGridUtils
public static makeColumnFromField = (field: QFieldMetaData, tableMetaData: QTableMetaData, namePrefix?: string, labelPrefix?: string): GridColDef =>
{
let columnType = "string";
- let filterOperators: GridFilterOperator[] = QGridStringOperators;
if (field.possibleValueSourceName)
{
- filterOperators = buildQGridPvsOperators(tableMetaData.name, field);
+ // noop here
}
else
{
@@ -308,22 +259,17 @@ export default class DataGridUtils
case QFieldType.DECIMAL:
case QFieldType.INTEGER:
columnType = "number";
- filterOperators = QGridNumericOperators;
break;
case QFieldType.DATE:
columnType = "date";
- filterOperators = QGridDateOperators;
break;
case QFieldType.DATE_TIME:
columnType = "dateTime";
- filterOperators = QGridDateTimeOperators;
break;
case QFieldType.BOOLEAN:
columnType = "string"; // using boolean gives an odd 'no' for nulls.
- filterOperators = QGridBooleanOperators;
break;
case QFieldType.BLOB:
- filterOperators = QGridBlobOperators;
break;
default:
// noop - leave as string
@@ -339,7 +285,6 @@ export default class DataGridUtils
headerName: headerName,
width: DataGridUtils.getColumnWidthForField(field, tableMetaData),
renderCell: null as any,
- filterOperators: filterOperators,
};
column.renderCell = (cellValues: any) => (