CE-793 - More cleanup from initial pre-qa qa (human words, values, expressions)

This commit is contained in:
2024-01-31 09:46:59 -06:00
parent 3858b40c0f
commit e96a189721
7 changed files with 145 additions and 24 deletions

View File

@ -321,9 +321,14 @@ function DynamicSelect({tableName, processName, fieldName, overrideId, fieldLabe
{ {
setOpen(false); setOpen(false);
}} }}
isOptionEqualToValue={(option, value) => option.id === value.id} isOptionEqualToValue={(option, value) => value !== null && value !== undefined && option.id === value.id}
getOptionLabel={(option) => getOptionLabel={(option) =>
{ {
if(option === null || option === undefined)
{
return ("");
}
// @ts-ignore // @ts-ignore
if(option && option.length) if(option && option.length)
{ {

View File

@ -47,7 +47,6 @@ import FormData from "form-data";
import React, {useEffect, useRef, useState} from "react"; import React, {useEffect, useRef, useState} from "react";
import {useLocation, useNavigate} from "react-router-dom"; import {useLocation, useNavigate} from "react-router-dom";
import {QCancelButton, QDeleteButton, QSaveButton, QSavedViewsMenuButton} from "qqq/components/buttons/DefaultButtons"; import {QCancelButton, QDeleteButton, QSaveButton, QSavedViewsMenuButton} from "qqq/components/buttons/DefaultButtons";
import CustomWidthTooltip from "qqq/components/tooltips/CustomWidthTooltip";
import QQueryColumns from "qqq/models/query/QQueryColumns"; import QQueryColumns from "qqq/models/query/QQueryColumns";
import RecordQueryView from "qqq/models/query/RecordQueryView"; import RecordQueryView from "qqq/models/query/RecordQueryView";
import FilterUtils from "qqq/utils/qqq/FilterUtils"; import FilterUtils from "qqq/utils/qqq/FilterUtils";
@ -390,8 +389,8 @@ function SavedViews({qController, metaData, tableMetaData, currentSavedView, vie
} }
}; };
diffVisibilityFunction(savedView.queryColumns, activeView.queryColumns, "Turned on visibility for "); diffVisibilityFunction(savedView.queryColumns, activeView.queryColumns, "Turned on ");
diffVisibilityFunction(activeView.queryColumns, savedView.queryColumns, "Turned off visibility for "); diffVisibilityFunction(activeView.queryColumns, savedView.queryColumns, "Turned off ");
diffPinsFunction(savedView.queryColumns, activeView.queryColumns, "Changed pinned state for "); diffPinsFunction(savedView.queryColumns, activeView.queryColumns, "Changed pinned state for ");
if(savedView.queryColumns.columns.map(c => c.name).join(",") != activeView.queryColumns.columns.map(c => c.name).join(",")) if(savedView.queryColumns.columns.map(c => c.name).join(",") != activeView.queryColumns.columns.map(c => c.name).join(","))

View File

@ -347,7 +347,8 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
<span> <span>
{queryFilter.criteria.map((criteria, i) => {queryFilter.criteria.map((criteria, i) =>
{ {
if(criteria && criteria.fieldName && criteria.operator) const {criteriaIsValid} = validateCriteria(criteria, null);
if(criteriaIsValid)
{ {
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, criteria.fieldName); const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, criteria.fieldName);
counter++; counter++;

View File

@ -53,6 +53,27 @@ export enum ValueMode
PVS_MULTI = "PVS_MULTI", PVS_MULTI = "PVS_MULTI",
} }
const getValueModeRequiredCount = (valueMode: ValueMode): number =>
{
switch (valueMode)
{
case ValueMode.NONE:
return (0);
case ValueMode.SINGLE:
case ValueMode.SINGLE_DATE:
case ValueMode.SINGLE_DATE_TIME:
case ValueMode.PVS_SINGLE:
return (1);
case ValueMode.DOUBLE:
case ValueMode.DOUBLE_DATE:
case ValueMode.DOUBLE_DATE_TIME:
return (2);
case ValueMode.MULTI:
case ValueMode.PVS_MULTI:
return (null);
}
}
export interface OperatorOption export interface OperatorOption
{ {
label: string; label: string;
@ -367,6 +388,24 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria,
{ {
criteria.values = newValue.implicitValues; 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 else
{ {

View File

@ -21,6 +21,7 @@
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter"; import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
import QQueryColumns, {PreLoadQueryColumns} from "qqq/models/query/QQueryColumns"; import QQueryColumns, {PreLoadQueryColumns} from "qqq/models/query/QQueryColumns";
import FilterUtils from "qqq/utils/qqq/FilterUtils";
/******************************************************************************* /*******************************************************************************
@ -62,6 +63,23 @@ export default class RecordQueryView
view.queryFilter = json.queryFilter as QQueryFilter; view.queryFilter = json.queryFilter as QQueryFilter;
//////////////////////////////////////////////////////////////////////////////////////////
// it's important that some criteria values exist as expression objects - so - do that. //
//////////////////////////////////////////////////////////////////////////////////////////
for (let i = 0; i < view.queryFilter?.criteria?.length; i++)
{
const criteria = view.queryFilter.criteria[i]
for (let j = 0; j < criteria?.values?.length; j++)
{
const value = criteria.values[j];
const expression = FilterUtils.gridCriteriaValueToExpression(value);
if(expression)
{
criteria.values[j] = expression;
}
}
}
if(json.queryColumns) if(json.queryColumns)
{ {
view.queryColumns = QQueryColumns.buildFromJSON(json.queryColumns); view.queryColumns = QQueryColumns.buildFromJSON(json.queryColumns);

View File

@ -78,7 +78,6 @@ import TableUtils from "qqq/utils/qqq/TableUtils";
import ValueUtils from "qqq/utils/qqq/ValueUtils"; import ValueUtils from "qqq/utils/qqq/ValueUtils";
const CURRENT_SAVED_VIEW_ID_LOCAL_STORAGE_KEY_ROOT = "qqq.currentSavedViewId"; const CURRENT_SAVED_VIEW_ID_LOCAL_STORAGE_KEY_ROOT = "qqq.currentSavedViewId";
const SEEN_JOIN_TABLES_LOCAL_STORAGE_KEY_ROOT = "qqq.seenJoinTables";
const DENSITY_LOCAL_STORAGE_KEY_ROOT = "qqq.density"; const DENSITY_LOCAL_STORAGE_KEY_ROOT = "qqq.density";
const VIEW_LOCAL_STORAGE_KEY_ROOT = "qqq.recordQueryView"; const VIEW_LOCAL_STORAGE_KEY_ROOT = "qqq.recordQueryView";
@ -159,7 +158,6 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
// look for defaults in the local storage // // look for defaults in the local storage //
//////////////////////////////////////////// ////////////////////////////////////////////
const currentSavedViewLocalStorageKey = `${CURRENT_SAVED_VIEW_ID_LOCAL_STORAGE_KEY_ROOT}.${tableName}`; const currentSavedViewLocalStorageKey = `${CURRENT_SAVED_VIEW_ID_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
const seenJoinTablesLocalStorageKey = `${SEEN_JOIN_TABLES_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
const tableVariantLocalStorageKey = `${TABLE_VARIANT_LOCAL_STORAGE_KEY_ROOT}.${tableName}`; const tableVariantLocalStorageKey = `${TABLE_VARIANT_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
const viewLocalStorageKey = `${VIEW_LOCAL_STORAGE_KEY_ROOT}.${tableName}`; const viewLocalStorageKey = `${VIEW_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
@ -167,10 +165,8 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
// define some default values (e.g., to be used if nothing in local storage or no active view) // // define some default values (e.g., to be used if nothing in local storage or no active view) //
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
let defaultSort = [] as GridSortItem[]; let defaultSort = [] as GridSortItem[];
let didDefaultVisibilityComeFromLocalStorage = false;
let defaultRowsPerPage = 10; let defaultRowsPerPage = 10;
let defaultDensity = "standard" as GridDensity; let defaultDensity = "standard" as GridDensity;
let seenJoinTables: {[tableName: string]: boolean} = {};
let defaultTableVariant: QTableVariant = null; let defaultTableVariant: QTableVariant = null;
let defaultMode = "basic"; let defaultMode = "basic";
let defaultQueryColumns: QQueryColumns = new PreLoadQueryColumns(); let defaultQueryColumns: QQueryColumns = new PreLoadQueryColumns();
@ -188,10 +184,6 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
{ {
defaultDensity = JSON.parse(localStorage.getItem(densityLocalStorageKey)); defaultDensity = JSON.parse(localStorage.getItem(densityLocalStorageKey));
} }
if (localStorage.getItem(seenJoinTablesLocalStorageKey))
{
seenJoinTables = JSON.parse(localStorage.getItem(seenJoinTablesLocalStorageKey));
}
if (localStorage.getItem(tableVariantLocalStorageKey)) if (localStorage.getItem(tableVariantLocalStorageKey))
{ {
defaultTableVariant = JSON.parse(localStorage.getItem(tableVariantLocalStorageKey)); defaultTableVariant = JSON.parse(localStorage.getItem(tableVariantLocalStorageKey));
@ -719,6 +711,13 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
{ {
if(pageState != "ready") if(pageState != "ready")
{ {
console.log(`In updateTable, but pageSate[${pageState}] is not ready, so returning with noop`);
return;
}
if(tableMetaData?.usesVariants && (!tableVariant || tableVariantPromptOpen))
{
console.log("In updateTable, but a variant is needed, so returning with noop");
return; return;
} }

View File

@ -189,7 +189,7 @@ class FilterUtils
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
private static gridCriteriaValueToExpression(value: any) public static gridCriteriaValueToExpression(value: any)
{ {
if (value && value.length) if (value && value.length)
{ {
@ -311,6 +311,15 @@ class FilterUtils
public static getValuesString(fieldMetaData: QFieldMetaData, criteria: QFilterCriteria, maxValuesToShow: number = 3): string public static getValuesString(fieldMetaData: QFieldMetaData, criteria: QFilterCriteria, maxValuesToShow: number = 3): string
{ {
let valuesString = ""; let valuesString = "";
if(criteria.operator == QCriteriaOperator.IS_BLANK || criteria.operator == QCriteriaOperator.IS_NOT_BLANK)
{
///////////////////////////////////////////////
// we don't want values for these operators. //
///////////////////////////////////////////////
return valuesString;
}
if (criteria.values && criteria.values.length) if (criteria.values && criteria.values.length)
{ {
let labels = [] as string[]; let labels = [] as string[];
@ -323,17 +332,41 @@ class FilterUtils
for (let i = 0; i < maxLoops; i++) for (let i = 0; i < maxLoops; i++)
{ {
if(fieldMetaData.type == QFieldType.BOOLEAN) const value = criteria.values[i];
if (value.type == "NowWithOffset")
{ {
labels.push(criteria.values[i] == true ? "yes" : "no") const expression = new NowWithOffsetExpression(value);
labels.push(expression.toString());
} }
else if (criteria.values[i] && criteria.values[i].label) else if (value.type == "Now")
{ {
labels.push(criteria.values[i].label); const expression = new NowExpression(value);
labels.push(expression.toString());
}
else if (value.type == "ThisOrLastPeriod")
{
const expression = new ThisOrLastPeriodExpression(value);
labels.push(expression.toString());
}
else if(fieldMetaData.type == QFieldType.BOOLEAN)
{
labels.push(value == true ? "yes" : "no")
}
else if(fieldMetaData.type == QFieldType.DATE_TIME)
{
labels.push(ValueUtils.formatDateTime(value));
}
else if(fieldMetaData.type == QFieldType.DATE)
{
labels.push(ValueUtils.formatDate(value));
}
else if (value && value.label)
{
labels.push(value.label);
} }
else else
{ {
labels.push(criteria.values[i]); labels.push(value);
} }
} }
@ -395,13 +428,16 @@ class FilterUtils
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
public static operatorToHumanString(criteria: QFilterCriteria): string public static operatorToHumanString(criteria: QFilterCriteria, field: QFieldMetaData): string
{ {
if(criteria == null || criteria.operator == null) if(criteria == null || criteria.operator == null)
{ {
return (null); return (null);
} }
const isDate = field.type == QFieldType.DATE;
const isDateTime = field.type == QFieldType.DATE_TIME;
try try
{ {
switch(criteria.operator) switch(criteria.operator)
@ -428,17 +464,41 @@ class FilterUtils
case QCriteriaOperator.NOT_CONTAINS: case QCriteriaOperator.NOT_CONTAINS:
return ("does not contain"); return ("does not contain");
case QCriteriaOperator.LESS_THAN: case QCriteriaOperator.LESS_THAN:
if(isDate || isDateTime)
{
return ("is before")
}
return ("less than"); return ("less than");
case QCriteriaOperator.LESS_THAN_OR_EQUALS: case QCriteriaOperator.LESS_THAN_OR_EQUALS:
if(isDate)
{
return ("is on or before")
}
if(isDateTime)
{
return ("is at or before")
}
return ("less than or equals"); return ("less than or equals");
case QCriteriaOperator.GREATER_THAN: case QCriteriaOperator.GREATER_THAN:
if(isDate || isDateTime)
{
return ("is after")
}
return ("greater than or equals"); return ("greater than or equals");
case QCriteriaOperator.GREATER_THAN_OR_EQUALS: case QCriteriaOperator.GREATER_THAN_OR_EQUALS:
if(isDate)
{
return ("is on or after")
}
if(isDateTime)
{
return ("is at or after")
}
return ("greater than or equals"); return ("greater than or equals");
case QCriteriaOperator.IS_BLANK: case QCriteriaOperator.IS_BLANK:
return ("is blank"); return ("is empty");
case QCriteriaOperator.IS_NOT_BLANK: case QCriteriaOperator.IS_NOT_BLANK:
return ("is not blank"); return ("is not empty");
case QCriteriaOperator.BETWEEN: case QCriteriaOperator.BETWEEN:
return ("is between"); return ("is between");
case QCriteriaOperator.NOT_BETWEEN: case QCriteriaOperator.NOT_BETWEEN:
@ -470,12 +530,12 @@ class FilterUtils
if(styled) if(styled)
{ {
return (<> return (<>
<b>{fieldLabel}</b> {FilterUtils.operatorToHumanString(criteria)} <span style={{color: "#0062FF"}}>{valuesString}</span>&nbsp; <b>{fieldLabel}</b> {FilterUtils.operatorToHumanString(criteria, field)} <span style={{color: "#0062FF"}}>{valuesString}</span>&nbsp;
</>); </>);
} }
else else
{ {
return (`${fieldLabel} ${FilterUtils.operatorToHumanString(criteria)} ${valuesString}`); return (`${fieldLabel} ${FilterUtils.operatorToHumanString(criteria, field)} ${valuesString}`);
} }
} }