diff --git a/src/qqq/components/query/AdvancedDateTimeFilterValues.tsx b/src/qqq/components/query/AdvancedDateTimeFilterValues.tsx
index fe08c19..c94919f 100644
--- a/src/qqq/components/query/AdvancedDateTimeFilterValues.tsx
+++ b/src/qqq/components/query/AdvancedDateTimeFilterValues.tsx
@@ -19,7 +19,10 @@
* along with this program. If not, see .
*/
+import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
+import {NowExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/NowExpression";
import {NowWithOffsetExpression, NowWithOffsetOperator, NowWithOffsetUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/NowWithOffsetExpression";
+import {ThisOrLastPeriodExpression, ThisOrLastPeriodOperator, ThisOrLastPeriodUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/ThisOrLastPeriodExpression";
import {FormControl, FormControlLabel, Radio, RadioGroup, Select} from "@mui/material";
import Box from "@mui/material/Box";
import Card from "@mui/material/Card";
@@ -37,33 +40,57 @@ import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons"
interface Props
{
- type: "date" | "datetime";
+ type: QFieldType
expression: any;
onSave: (expression: any) => void;
}
AdvancedDateTimeFilterValues.defaultProps = {};
+const extractExpressionType = (expression: any) => expression?.type ?? "NowWithOffset";
+const extractNowWithOffsetAmount = (expression: any) => expression?.type == "NowWithOffset" ? (expression?.amount ?? 1) : 1;
+const extractNowWithOffsetTimeUnit = (expression: any) => expression?.type == "NowWithOffset" ? (expression?.timeUnit ?? "DAYS") : "DAYS" as NowWithOffsetUnit;
+const extractNowWithOffsetOperator = (expression: any) => expression?.type == "NowWithOffset" ? (expression?.operator ?? "MINUS") : "MINUS" as NowWithOffsetOperator;
+const extractThisOrLastPeriodTimeUnit = (expression: any) => expression?.type == "ThisOrLastPeriod" ? (expression?.timeUnit ?? "DAYS") : "DAYS" as ThisOrLastPeriodUnit;
+const extractThisOrLastPeriodOperator = (expression: any) => expression?.type == "ThisOrLastPeriod" ? (expression?.operator ?? "THIS") : "THIS" as ThisOrLastPeriodOperator;
+
function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.Element
{
const [originalExpression, setOriginalExpression] = useState(JSON.stringify(expression));
- const [expressionType, setExpressionType] = useState(expression?.type ?? "NowWithOffset")
+ const [expressionType, setExpressionType] = useState(extractExpressionType(expression))
+
+ const [nowWithOffsetAmount, setNowWithOffsetAmount] = useState(extractNowWithOffsetAmount(expression));
+ const [nowWithOffsetTimeUnit, setNowWithOffsetTimeUnit] = useState(extractNowWithOffsetTimeUnit(expression));
+ const [nowWithOffsetOperator, setNowWithOffsetOperator] = useState(extractNowWithOffsetOperator(expression));
+
+ const [thisOrLastPeriodTimeUnit, setThisOrLastPeriodTimeUnit] = useState(extractThisOrLastPeriodTimeUnit(expression));
+ const [thisOrLastPeriodOperator, setThisOrLastPeriodOperator] = useState(extractThisOrLastPeriodOperator(expression));
- const [amount, setAmount] = useState(expression?.amount ?? 1)
- const [timeUnit, setTimeUnit] = useState(expression?.timeUnit ?? "DAYS" as NowWithOffsetUnit);
- const [operator, setOperator] = useState(expression?.operator ?? "MINUS" as NowWithOffsetOperator);
const [isOpen, setIsOpen] = useState(false)
+ const setStateToExpression = (activeExpression: any) =>
+ {
+ setExpressionType(extractExpressionType(activeExpression))
+
+ setNowWithOffsetAmount(extractNowWithOffsetAmount(activeExpression))
+ setNowWithOffsetTimeUnit(extractNowWithOffsetTimeUnit(activeExpression))
+ setNowWithOffsetOperator(extractNowWithOffsetOperator(activeExpression))
+
+ setThisOrLastPeriodTimeUnit(extractThisOrLastPeriodTimeUnit(activeExpression))
+ setThisOrLastPeriodOperator(extractThisOrLastPeriodOperator(activeExpression))
+ }
+
//////////////////////////////////////////////////////////////////////////////////
// if the expression (prop) has changed, re-set the state variables based on it //
//////////////////////////////////////////////////////////////////////////////////
if(JSON.stringify(expression) !== originalExpression)
{
- setExpressionType(expression?.type ?? "NowWithOffset")
- setAmount(expression?.amount ?? 1)
- setTimeUnit(expression?.timeUnit ?? "DAYS")
- setOperator(expression?.operator ?? "MINUS")
+ ///////////////////////////////////////////////////////////
+ // update all state vars based on the current expression //
+ ///////////////////////////////////////////////////////////
+ setStateToExpression(expression);
+
setOriginalExpression(JSON.stringify(expression))
}
@@ -72,17 +99,47 @@ function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.El
setIsOpen(true);
}
+ const handleCancelClicked = () =>
+ {
+ ///////////////////////////////////////////////////////////
+ // update all state vars back to the original expression //
+ ///////////////////////////////////////////////////////////
+ const restoreExpression = JSON.parse(originalExpression)
+ setStateToExpression(restoreExpression);
+
+ close();
+ }
+
const handleSaveClicked = () =>
{
switch(expressionType)
{
+ case "Now":
+ {
+ const expression = new NowExpression();
+ onSave(expression);
+ break;
+ }
case "NowWithOffset":
{
const expression = new NowWithOffsetExpression()
- expression.operator = operator;
- expression.amount = amount;
- expression.timeUnit = timeUnit;
+ expression.operator = nowWithOffsetOperator;
+ expression.amount = nowWithOffsetAmount;
+ expression.timeUnit = nowWithOffsetTimeUnit;
onSave(expression);
+ break;
+ }
+ case "ThisOrLastPeriod":
+ {
+ const expression = new ThisOrLastPeriodExpression()
+ expression.operator = thisOrLastPeriodOperator;
+ expression.timeUnit = thisOrLastPeriodTimeUnit;
+ onSave(expression);
+ break;
+ }
+ default:
+ {
+ console.log(`Unmapped expression type in handleSAveClicked: ${expressionType}`);
}
}
@@ -99,35 +156,47 @@ function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.El
setExpressionType(e.target.value);
}
- function handleAmountChange(event: React.ChangeEvent)
+ function handleNowWithOffsetAmountChange(event: React.ChangeEvent)
{
- setAmount(parseInt(event.target.value));
+ setNowWithOffsetAmount(parseInt(event.target.value));
}
- function handleTimeUnitChange(event: SelectChangeEvent, child: ReactNode)
+ function handleNowWithOffsetTimeUnitChange(event: SelectChangeEvent, child: ReactNode)
{
// @ts-ignore
- setTimeUnit(event.target.value)
+ setNowWithOffsetTimeUnit(event.target.value)
}
- function handleOperatorChange(event: SelectChangeEvent, child: ReactNode)
+ function handleNowWithOffsetOperatorChange(event: SelectChangeEvent, child: ReactNode)
{
// @ts-ignore
- setOperator(event.target.value)
+ setNowWithOffsetOperator(event.target.value)
}
+ function handleThisOrLastPeriodTimeUnitChange(event: SelectChangeEvent, child: ReactNode)
+ {
+ // @ts-ignore
+ setThisOrLastPeriodTimeUnit(event.target.value)
+ }
+
+ function handleThisOrLastPeriodOperatorChange(event: SelectChangeEvent, child: ReactNode)
+ {
+ // @ts-ignore
+ setThisOrLastPeriodOperator(event.target.value)
+ }
const mainCardStyles: any = {};
mainCardStyles.width = "600px";
/////////////////////////////////////////////////////////////////////////
// for the time units, have them end in an 's' if the amount is plural //
+ // name here means "time unit 's'" //
/////////////////////////////////////////////////////////////////////////
- const tuS = (amount == 1 ? "" : "s");
+ const nwoTUs = (nowWithOffsetAmount == 1 ? "" : "s");
return (
-
+
settings
{
@@ -150,6 +219,10 @@ function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.El
+
+ } label="Now" />
+
+
} label="Relative Expression" />
@@ -159,26 +232,26 @@ function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.El
type="number"
inputProps={{min: 0}}
autoComplete="off"
- value={amount}
- onChange={(event) => handleAmountChange(event)}
+ value={nowWithOffsetAmount}
+ onChange={(event) => handleNowWithOffsetAmountChange(event)}
fullWidth
/>
-
-
+
@@ -186,10 +259,34 @@ function AdvancedDateTimeFilterValues({type, expression, onSave}: Props): JSX.El
+
+ } label={`${type == QFieldType.DATE_TIME ? "Start of " : ""}This or Last...`} />
+
+
+
+
+
+
+
+
+
+
+
+ {type == QFieldType.DATE_TIME && }
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/qqq/components/query/CriteriaDateField.tsx b/src/qqq/components/query/CriteriaDateField.tsx
new file mode 100644
index 0000000..c6b7c00
--- /dev/null
+++ b/src/qqq/components/query/CriteriaDateField.tsx
@@ -0,0 +1,221 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. 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 {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
+import {NowExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/NowExpression";
+import {NowWithOffsetExpression, NowWithOffsetOperator, NowWithOffsetUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/NowWithOffsetExpression";
+import {ThisOrLastPeriodExpression, ThisOrLastPeriodOperator, ThisOrLastPeriodUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/ThisOrLastPeriodExpression";
+import Box from "@mui/material/Box";
+import Icon from "@mui/material/Icon";
+import IconButton from "@mui/material/IconButton";
+import InputAdornment from "@mui/material/InputAdornment/InputAdornment";
+import Menu from "@mui/material/Menu";
+import MenuItem from "@mui/material/MenuItem";
+import TextField from "@mui/material/TextField";
+import Tooltip from "@mui/material/Tooltip";
+import React, {SyntheticEvent, useReducer, useState} from "react";
+import AdvancedDateTimeFilterValues from "qqq/components/query/AdvancedDateTimeFilterValues";
+import {QFilterCriteriaWithId} from "qqq/components/query/CustomFilterPanel";
+import {makeTextField} from "qqq/components/query/FilterCriteriaRowValues";
+
+interface CriteriaDateFieldProps
+{
+ valueIndex: number;
+ label: string;
+ idPrefix: string;
+ field: QFieldMetaData;
+ criteria: QFilterCriteriaWithId;
+ valueChangeHandler: (event: React.ChangeEvent | SyntheticEvent, valueIndex?: number | "all", newValue?: any) => void;
+}
+
+CriteriaDateField.defaultProps = {
+ valueIndex: 0,
+ label: "Value",
+ idPrefix: "value-"
+};
+
+export default function CriteriaDateField({valueIndex, label, idPrefix, field, criteria, valueChangeHandler}: CriteriaDateFieldProps): JSX.Element
+{
+ const [relativeDateTimeMenuAnchorElement, setRelativeDateTimeMenuAnchorElement] = useState(null);
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
+
+ const openRelativeDateTimeMenu = (event: React.MouseEvent) =>
+ {
+ setRelativeDateTimeMenuAnchorElement(event.currentTarget);
+ };
+
+ const closeRelativeDateTimeMenu = () =>
+ {
+ setRelativeDateTimeMenuAnchorElement(null);
+ };
+
+ const setExpressionNow = (valueIndex: number) =>
+ {
+ const expression = new NowExpression()
+ saveNewDateTimeExpression(valueIndex, expression);
+
+ closeRelativeDateTimeMenu();
+ };
+
+ const setExpressionNowWithOffset = (valueIndex: number, operator: NowWithOffsetOperator, amount: number, timeUnit: NowWithOffsetUnit) =>
+ {
+ const expression = new NowWithOffsetExpression()
+ expression.operator = operator;
+ expression.amount = amount;
+ expression.timeUnit = timeUnit;
+
+ saveNewDateTimeExpression(valueIndex, expression);
+
+ closeRelativeDateTimeMenu();
+ };
+
+ const setExpressionThisOrLastPeriod = (valueIndex: number, operator: ThisOrLastPeriodOperator, timeUnit: ThisOrLastPeriodUnit) =>
+ {
+ const expression = new ThisOrLastPeriodExpression()
+ expression.operator = operator;
+ expression.timeUnit = timeUnit;
+
+ saveNewDateTimeExpression(valueIndex, expression);
+
+ closeRelativeDateTimeMenu();
+ };
+
+ function saveNewDateTimeExpression(valueIndex: number, expression: any)
+ {
+ valueChangeHandler(null, valueIndex, expression);
+ forceUpdate();
+ }
+
+ const makeDateTimeExpressionTextField = (expression: any, valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
+ {
+ const clearValue = (event: React.MouseEvent | React.MouseEvent, index: number) =>
+ {
+ valueChangeHandler(event, index, "");
+ forceUpdate()
+ document.getElementById(`${idPrefix}${criteria.id}`).focus();
+ };
+
+ const inputProps: any = {};
+ inputProps.endAdornment = (
+
+ clearValue(event, valueIndex)}>
+ close
+
+
+ );
+
+ let displayValue = expression.toString();
+ if (expression?.type == "ThisOrLastPeriod")
+ {
+ if(field.type == QFieldType.DATE_TIME || (field.type == QFieldType.DATE && expression.timeUnit != "DAYS"))
+ {
+ displayValue = "start of " + displayValue;
+ }
+ }
+
+ return ;
+ }
+
+ const isExpression = criteria.values && criteria.values[valueIndex] && criteria.values[valueIndex].type;
+ const currentExpression = isExpression ? criteria.values[valueIndex] : null;
+
+ return
+ {
+ isExpression ? makeDateTimeExpressionTextField(criteria.values[valueIndex], valueIndex, label, idPrefix)
+ : makeTextField(field, criteria, valueChangeHandler, valueIndex, label, idPrefix)
+ }
+
+
+ date_range
+
+
+
+
+ saveNewDateTimeExpression(valueIndex, expression)} />
+
+ ;
+}
diff --git a/src/qqq/components/query/FilterCriteriaRow.tsx b/src/qqq/components/query/FilterCriteriaRow.tsx
index 1f4049c..8114c63 100644
--- a/src/qqq/components/query/FilterCriteriaRow.tsx
+++ b/src/qqq/components/query/FilterCriteriaRow.tsx
@@ -343,24 +343,8 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria,
//////////////////////////////////////////////////
// event handler for value field (of all types) //
//////////////////////////////////////////////////
- const handleValueChange = (event: React.ChangeEvent | SyntheticEvent, valueIndex: number | "all" = 0, newValue?: any, newExpression?: any) =>
+ const handleValueChange = (event: React.ChangeEvent | SyntheticEvent, valueIndex: number | "all" = 0, newValue?: any) =>
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- // if an expression was passed in - put it on the criteria, removing the values. //
- // else - if no expression - make sure criteria.expression is null, and do the various values logics //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- if(newExpression)
- {
- criteria.expression = newExpression;
- criteria.values = null;
- updateCriteria(criteria, true);
- return;
- }
- else
- {
- criteria.expression = null;
- }
-
// @ts-ignore
const value = newValue !== undefined ? newValue : event ? event.target.value : null;
@@ -471,15 +455,9 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria,
// don't need to look at values //
//////////////////////////////////
}
- else if (criteria.expression)
+ else if(operatorSelectedValue.valueMode == ValueMode.DOUBLE || operatorSelectedValue.valueMode == ValueMode.DOUBLE_DATE || operatorSelectedValue.valueMode == ValueMode.DOUBLE_DATE_TIME)
{
- ////////////////////////////////////////////////////////
- // if there's an expression - let's assume it's valid //
- ////////////////////////////////////////////////////////
- }
- else if(operatorSelectedValue.valueMode == ValueMode.DOUBLE)
- {
- if(criteria.values.length < 2)
+ if(criteria.values.length < 2 || isNotSet(criteria.values[0]) || isNotSet(criteria.values[1]))
{
criteriaIsValid = false;
criteriaStatusTooltip = "You must enter two values to complete the definition of this condition.";
@@ -563,7 +541,7 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria,
criteria={{id: id, ...criteria}}
field={field}
table={fieldTable}
- valueChangeHandler={(event, valueIndex, newValue, newExpression) => handleValueChange(event, valueIndex, newValue, newExpression)}
+ valueChangeHandler={(event, valueIndex, newValue) => handleValueChange(event, valueIndex, newValue)}
/>
diff --git a/src/qqq/components/query/FilterCriteriaRowValues.tsx b/src/qqq/components/query/FilterCriteriaRowValues.tsx
index 8be4182..d1eb339 100644
--- a/src/qqq/components/query/FilterCriteriaRowValues.tsx
+++ b/src/qqq/components/query/FilterCriteriaRowValues.tsx
@@ -23,21 +23,15 @@
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
-import {NowWithOffsetExpression, NowWithOffsetOperator, NowWithOffsetUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/NowWithOffsetExpression";
-import {ThisOrLastPeriodExpression, ThisOrLastPeriodOperator, ThisOrLastPeriodUnit} from "@kingsrook/qqq-frontend-core/lib/model/query/ThisOrLastPeriodExpression";
import Autocomplete from "@mui/material/Autocomplete";
import Box from "@mui/material/Box";
import Icon from "@mui/material/Icon";
import IconButton from "@mui/material/IconButton";
import InputAdornment from "@mui/material/InputAdornment/InputAdornment";
-import Menu from "@mui/material/Menu";
-import MenuItem from "@mui/material/MenuItem";
-import Select, {SelectChangeEvent} from "@mui/material/Select/Select";
import TextField from "@mui/material/TextField";
-import Tooltip from "@mui/material/Tooltip";
-import React, {ReactNode, SyntheticEvent, useReducer, useState} from "react";
+import React, {SyntheticEvent, useReducer} from "react";
import DynamicSelect from "qqq/components/forms/DynamicSelect";
-import AdvancedDateTimeFilterValues from "qqq/components/query/AdvancedDateTimeFilterValues";
+import CriteriaDateField from "qqq/components/query/CriteriaDateField";
import {QFilterCriteriaWithId} from "qqq/components/query/CustomFilterPanel";
import FilterCriteriaPaster from "qqq/components/query/FilterCriteriaPaster";
import {OperatorOption, ValueMode} from "qqq/components/query/FilterCriteriaRow";
@@ -49,16 +43,78 @@ interface Props
criteria: QFilterCriteriaWithId;
field: QFieldMetaData;
table: QTableMetaData;
- valueChangeHandler: (event: React.ChangeEvent | SyntheticEvent, valueIndex?: number | "all", newValue?: any, newExpression?: any) => void;
+ valueChangeHandler: (event: React.ChangeEvent | SyntheticEvent, valueIndex?: number | "all", newValue?: any) => void;
}
-FilterCriteriaRowValues.defaultProps = {
+FilterCriteriaRowValues.defaultProps = {};
+
+export const getTypeForTextField = (field: QFieldMetaData): string =>
+{
+ let type = "search";
+
+ if (field.type == QFieldType.INTEGER)
+ {
+ type = "number";
+ }
+ else if (field.type == QFieldType.DATE)
+ {
+ type = "date";
+ }
+ else if (field.type == QFieldType.DATE_TIME)
+ {
+ type = "datetime-local";
+ }
+
+ return (type);
+};
+
+export const makeTextField = (field: QFieldMetaData, criteria: QFilterCriteriaWithId, valueChangeHandler?: (event: (React.ChangeEvent | React.SyntheticEvent), valueIndex?: (number | "all"), newValue?: any) => void, valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
+{
+ let type = getTypeForTextField(field);
+ const inputLabelProps: any = {};
+
+ if (field.type == QFieldType.DATE || field.type == QFieldType.DATE_TIME)
+ {
+ inputLabelProps.shrink = true;
+ }
+
+ let value = criteria.values[valueIndex];
+ if (field.type == QFieldType.DATE_TIME && value && String(value).indexOf("Z") > -1)
+ {
+ value = ValueUtils.formatDateTimeValueForForm(value);
+ }
+
+ const clearValue = (event: React.MouseEvent | React.MouseEvent, index: number) =>
+ {
+ valueChangeHandler(event, index, "");
+ document.getElementById(`${idPrefix}${criteria.id}`).focus();
+ };
+
+ const inputProps: any = {};
+ inputProps.endAdornment = (
+
+ clearValue(event, valueIndex)}>
+ close
+
+
+ );
+
+ return valueChangeHandler(event, valueIndex)}
+ value={value}
+ InputLabelProps={inputLabelProps}
+ InputProps={inputProps}
+ fullWidth
+ />;
};
function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueChangeHandler}: Props): JSX.Element
{
- const [relativeDateTimeMenuAnchorElement, setRelativeDateTimeMenuAnchorElement] = useState(null);
-
const [, forceUpdate] = useReducer((x) => x + 1, 0);
if (!operatorOption)
@@ -66,197 +122,6 @@ function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueC
return
;
}
- const getTypeForTextField = (): string =>
- {
- let type = "search";
-
- if (field.type == QFieldType.INTEGER)
- {
- type = "number";
- }
- else if (field.type == QFieldType.DATE)
- {
- type = "date";
- }
- else if (field.type == QFieldType.DATE_TIME)
- {
- type = "datetime-local";
- }
-
- return (type);
- };
-
- const makeTextField = (valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
- {
- let type = getTypeForTextField();
- const inputLabelProps: any = {};
-
- if (field.type == QFieldType.DATE || field.type == QFieldType.DATE_TIME)
- {
- inputLabelProps.shrink = true;
- }
-
- let value = criteria.values[valueIndex];
- if (field.type == QFieldType.DATE_TIME && value && String(value).indexOf("Z") > -1)
- {
- value = ValueUtils.formatDateTimeValueForForm(value);
- }
-
- const clearValue = (event: React.MouseEvent | React.MouseEvent, index: number) =>
- {
- valueChangeHandler(event, index, "");
- document.getElementById(`${idPrefix}${criteria.id}`).focus();
- };
-
- const inputProps: any = {};
- inputProps.endAdornment = (
-
- clearValue(event, valueIndex)}>
- close
-
-
- );
-
- return valueChangeHandler(event, valueIndex)}
- value={value}
- InputLabelProps={inputLabelProps}
- InputProps={inputProps}
- fullWidth
- />;
- };
-
- const makeDateTimeExpressionTextField = (expression: any, valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
- {
- const clearValue = (event: React.MouseEvent | React.MouseEvent, index: number) =>
- {
- valueChangeHandler(event, index, "");
- forceUpdate()
- document.getElementById(`${idPrefix}${criteria.id}`).focus();
- };
-
- const inputProps: any = {};
- inputProps.endAdornment = (
-
- clearValue(event, valueIndex)}>
- close
-
-
- );
-
- let displayValue = expression.toString();
- if (expression?.type == "ThisOrLastPeriod")
- {
- if(field.type == QFieldType.DATE_TIME || (field.type == QFieldType.DATE && expression.timeUnit != "DAYS"))
- {
- displayValue = "start of " + displayValue;
- }
- }
-
- return ;
- }
-
- const makeDateField = (valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
- {
- return
- {
- criteria.expression == null && makeTextField(valueIndex, label, idPrefix)
- }
- {
- criteria.expression != null && makeDateTimeExpressionTextField(criteria.expression, valueIndex, label, idPrefix)
- }
-
-
- date_range
-
-
-
-
- saveNewDateTimeExpression(valueIndex, expression)} />
-
- ;
- }
-
- const makeDateTimeField = (valueIndex: number = 0, label = "Value", idPrefix = "value-") =>
- {
- return
- {
- criteria.expression == null && makeTextField(valueIndex, label, idPrefix)
- }
- {
- criteria.expression != null && makeDateTimeExpressionTextField(criteria.expression, valueIndex, label, idPrefix)
- }
-
-
- date_range
-
-
-
-
- saveNewDateTimeExpression(valueIndex, expression)} />
-
- ;
- }
-
function saveNewPasterValues(newValues: any[])
{
if (criteria.values)
@@ -280,69 +145,33 @@ function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueC
forceUpdate();
}
- const openRelativeDateTimeMenu = (event: React.MouseEvent) =>
- {
- setRelativeDateTimeMenuAnchorElement(event.currentTarget);
- };
-
- const closeRelativeDateTimeMenu = () =>
- {
- setRelativeDateTimeMenuAnchorElement(null);
- };
-
- const setExpressionNowWithOffset = (valueIndex: number, operator: NowWithOffsetOperator, amount: number, timeUnit: NowWithOffsetUnit) =>
- {
- const expression = new NowWithOffsetExpression()
- expression.operator = operator;
- expression.amount = amount;
- expression.timeUnit = timeUnit;
-
- saveNewDateTimeExpression(valueIndex, expression);
-
- closeRelativeDateTimeMenu();
- };
-
- const setExpressionThisOrLastPeriod = (valueIndex: number, operator: ThisOrLastPeriodOperator, timeUnit: ThisOrLastPeriodUnit) =>
- {
- const expression = new ThisOrLastPeriodExpression()
- expression.operator = operator;
- expression.timeUnit = timeUnit;
-
- saveNewDateTimeExpression(valueIndex, expression);
-
- closeRelativeDateTimeMenu();
- };
-
- function saveNewDateTimeExpression(valueIndex: number, expression: any)
- {
- criteria.expression = expression;
- criteria.values = null;
- valueChangeHandler(null, valueIndex, null, expression);
- forceUpdate();
- }
-
switch (operatorOption.valueMode)
{
case ValueMode.NONE:
return
;
case ValueMode.SINGLE:
- return makeTextField();
+ return makeTextField(field, criteria, valueChangeHandler);
case ValueMode.SINGLE_DATE:
- return makeDateField();
+ return ;
case ValueMode.DOUBLE_DATE:
return
- {makeDateField(0, "From", "from-")}
- {makeDateField(1, "To", "to-")}
-
+
+
+ ;
case ValueMode.SINGLE_DATE_TIME:
- return makeDateTimeField();
+ return ;
+ case ValueMode.DOUBLE_DATE_TIME:
+ return
+
+
+ ;
case ValueMode.DOUBLE:
return
- { makeTextField(0, "From", "from-") }
+ {makeTextField(field, criteria, valueChangeHandler, 0, "From", "from-")}
- {makeTextField(1, "To", "to-")}
+ {makeTextField(field, criteria, valueChangeHandler, 1, "To", "to-")}
;
case ValueMode.MULTI:
@@ -365,7 +194,7 @@ function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueC
onChange={(event, value) => valueChangeHandler(event, "all", value)}
/>
- saveNewPasterValues(newValues)} />
+ saveNewPasterValues(newValues)} />
;
case ValueMode.PVS_SINGLE:
@@ -414,7 +243,7 @@ function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueC
inForm={false}
onChange={(value: any) => valueChangeHandler(null, "all", value)}
/>
-
+ ;
}
return (
);
diff --git a/src/qqq/utils/qqq/FilterUtils.ts b/src/qqq/utils/qqq/FilterUtils.ts
index 2c5b0dd..d3c4372 100644
--- a/src/qqq/utils/qqq/FilterUtils.ts
+++ b/src/qqq/utils/qqq/FilterUtils.ts
@@ -23,6 +23,7 @@ import {QController} from "@kingsrook/qqq-frontend-core/lib/controllers/QControl
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
+import {NowExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/NowExpression";
import {NowWithOffsetExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/NowWithOffsetExpression";
import {QCriteriaOperator} from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator";
import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterCriteria";
@@ -289,7 +290,7 @@ class FilterUtils
if (FilterUtils.gridCriteriaValueToExpression(param))
{
- return (null);
+ return (param);
}
let rs = [];
@@ -337,13 +338,8 @@ class FilterUtils
** Convert a filter field's value from the style that qqq uses, to the style that
** the grid uses.
*******************************************************************************/
- public static qqqCriteriaValuesToGrid = (operator: QCriteriaOperator, values: any[], expression: any, field: QFieldMetaData): any | any[] =>
+ public static qqqCriteriaValuesToGrid = (operator: QCriteriaOperator, values: any[], field: QFieldMetaData): any | any[] =>
{
- if(expression)
- {
- return (expression);
- }
-
const fieldType = field.type;
if (operator === QCriteriaOperator.IS_BLANK || operator === QCriteriaOperator.IS_NOT_BLANK)
{
@@ -361,7 +357,13 @@ class FilterUtils
////////////////////////////////////////////////////////////////////////////////////////////////
if (fieldType === QFieldType.DATE_TIME)
{
- values[0] = ValueUtils.formatDateTimeValueForForm(values[0]);
+ for(let i = 0; i