From a778b7497ad16b3fbb1544c5e58c68c23c96e455 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 4 Jun 2024 13:43:39 -0500 Subject: [PATCH] CE-938: updated to get filter and column setup values from widget data, rather than 'default values' --- src/qqq/components/forms/DynamicSelect.tsx | 78 ++++++++++--------- src/qqq/components/forms/EntityForm.tsx | 5 +- .../query/BasicAndAdvancedQueryControls.tsx | 4 + .../components/query/CustomFilterPanel.tsx | 1 + .../components/query/FilterCriteriaRow.tsx | 4 +- .../query/FilterCriteriaRowValues.tsx | 6 +- src/qqq/components/query/QuickFilter.tsx | 4 +- .../components/widgets/DashboardWidgets.tsx | 4 +- .../misc/FilterAndColumnsSetupWidget.tsx | 26 ++----- src/qqq/pages/records/query/RecordQuery.tsx | 5 +- 10 files changed, 70 insertions(+), 67 deletions(-) diff --git a/src/qqq/components/forms/DynamicSelect.tsx b/src/qqq/components/forms/DynamicSelect.tsx index f254872..35b3172 100644 --- a/src/qqq/components/forms/DynamicSelect.tsx +++ b/src/qqq/components/forms/DynamicSelect.tsx @@ -97,7 +97,7 @@ export const getAutocompleteOutlinedStyle = (isDisabled: boolean) => borderColor: inputBorderColor } }); -} +}; const qController = Client.getInstance(); @@ -108,36 +108,36 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa const [options, setOptions] = useState([]); const [searchTerm, setSearchTerm] = useState(null); const [firstRender, setFirstRender] = useState(true); - const [otherValuesWhenResultsWereLoaded, setOtherValuesWhenResultsWereLoaded] = useState(JSON.stringify(Object.fromEntries((otherValues)))) + const [otherValuesWhenResultsWereLoaded, setOtherValuesWhenResultsWereLoaded] = useState(JSON.stringify(Object.fromEntries((otherValues)))); useEffect(() => { - if(tableName && processName) + if (tableName && processName) { - console.log("DynamicSelect - you may not provide both a tableName and a processName") + console.log("DynamicSelect - you may not provide both a tableName and a processName"); } - if(tableName && !fieldName) + if (tableName && !fieldName) { console.log("DynamicSelect - if you provide a tableName, you must also provide a fieldName"); } - if(processName && !fieldName) + if (processName && !fieldName) { console.log("DynamicSelect - if you provide a processName, you must also provide a fieldName"); } - if(!fieldName && !possibleValueSourceName) + if (!fieldName && !possibleValueSourceName) { console.log("DynamicSelect - you must provide either a fieldName (and a tableName or processName) or a possibleValueSourceName"); } - if(fieldName && !possibleValueSourceName) + if (fieldName && !possibleValueSourceName) { - if(!tableName || !processName) + if (!tableName || !processName) { console.log("DynamicSelect - if you provide a fieldName and not a possibleValueSourceName, then you must also provide a tableName or processName"); } } - if(possibleValueSourceName) + if (possibleValueSourceName) { - if(tableName || processName) + if (tableName || processName) { console.log("DynamicSelect - if you provide a possibleValueSourceName, you should not also provide a tableName or processName"); } @@ -173,7 +173,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa useEffect(() => { - if(firstRender) + if (firstRender) { // console.log("First render, so not searching..."); setFirstRender(false); @@ -196,7 +196,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa // console.log(`doing a search with ${searchTerm}`); const results: QPossibleValue[] = await qController.possibleValues(tableName, processName, possibleValueSourceName ?? fieldName, searchTerm ?? "", null, otherValues); - if(tableMetaData == null && tableName) + if (tableMetaData == null && tableName) { let tableMetaData: QTableMetaData = await qController.loadTableMetaData(tableName); setTableMetaData(tableMetaData); @@ -207,7 +207,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa // console.log(`${results}`); if (active) { - setOptions([ ...results ]); + setOptions([...results]); } })(); @@ -215,12 +215,12 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa { active = false; }; - }, [ searchTerm ]); + }, [searchTerm]); // todo - finish... call it in onOpen? const reloadIfOtherValuesAreChanged = () => { - if(JSON.stringify(Object.fromEntries(otherValues)) != otherValuesWhenResultsWereLoaded) + if (JSON.stringify(Object.fromEntries(otherValues)) != otherValuesWhenResultsWereLoaded) { (async () => { @@ -229,16 +229,16 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa console.log("Refreshing possible values..."); const results: QPossibleValue[] = await qController.possibleValues(tableName, processName, possibleValueSourceName ?? fieldName, searchTerm ?? "", null, otherValues); setLoading(false); - setOptions([ ...results ]); + setOptions([...results]); setOtherValuesWhenResultsWereLoaded(JSON.stringify(Object.fromEntries(otherValues))); })(); } - } + }; const inputChanged = (event: React.SyntheticEvent, value: string, reason: string) => { // console.log(`input changed. Reason: ${reason}, setting search term to ${value}`); - if(reason !== "reset") + if (reason !== "reset") { // console.log(` -> setting search term to ${value}`); setSearchTerm(value); @@ -248,7 +248,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa const handleBlur = (x: any) => { setSearchTerm(null); - } + }; const handleChanged = (event: React.SyntheticEvent, value: any | any[], reason: string, details?: string) => { @@ -256,9 +256,9 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa // console.log(value); setSearchTerm(null); - if(onChange) + if (onChange) { - if(isMultiple) + if (isMultiple) { onChange(value); } @@ -267,7 +267,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa onChange(value ? new QPossibleValue(value) : null); } } - else if(setFieldValueRef && fieldName) + else if (setFieldValueRef && fieldName) { setFieldValueRef(fieldName, value ? value.id : null); } @@ -280,7 +280,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa // get options whose text/label matches the input (e.g., not ids that match) // ///////////////////////////////////////////////////////////////////////////////// return (options); - } + }; // @ts-ignore const renderOption = (props: Object, option: any, {selected}) => @@ -289,23 +289,24 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa try { - const field = tableMetaData?.fields.get(fieldName) - if(field) + const field = tableMetaData?.fields.get(fieldName); + if (field) { const adornment = field.getAdornment(AdornmentType.CHIP); - if(adornment) + if (adornment) { - const color = adornment.getValue("color." + option.id) ?? "default" + const color = adornment.getValue("color." + option.id) ?? "default"; const iconName = adornment.getValue("icon." + option.id) ?? null; const iconElement = iconName ? {iconName} : null; content = (); } } } - catch(e) - { } + catch (e) + { + } - if(isMultiple) + if (isMultiple) { content = ( <> @@ -327,7 +328,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa {content} ); - } + }; const bulkEditSwitchChanged = () => { @@ -357,7 +358,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa { setOpen(true); // console.log("setting open..."); - if(options.length == 0) + if (options.length == 0) { // console.log("no options yet, so setting search term to ''..."); setSearchTerm(""); @@ -370,19 +371,19 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa isOptionEqualToValue={(option, value) => value !== null && value !== undefined && option.id === value.id} getOptionLabel={(option) => { - if(option === null || option === undefined) + if (option === null || option === undefined) { return (""); } // @ts-ignore - if(option && option.length) + if (option && option.length) { // @ts-ignore option = option[0]; } // @ts-ignore - return option.label + return option.label; }} options={options} loading={loading} @@ -446,7 +447,8 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa id={`bulkEditSwitch-${fieldName}`} checked={switchChecked} onClick={bulkEditSwitchChanged} - sx={{top: "-4px", + sx={{ + top: "-4px", "& .MuiSwitch-track": { height: 20, borderRadius: 10, @@ -465,7 +467,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa else { return ( - + {autocomplete} ); diff --git a/src/qqq/components/forms/EntityForm.tsx b/src/qqq/components/forms/EntityForm.tsx index 57a3362..161d3a1 100644 --- a/src/qqq/components/forms/EntityForm.tsx +++ b/src/qqq/components/forms/EntityForm.tsx @@ -396,15 +396,16 @@ function EntityForm(props: Props): JSX.Element // if the widget metadata specifies a table name, set form values to that so widget knows which to use // // (for the case when it is not being specified by a separate field in the record) // ///////////////////////////////////////////////////////////////////////////////////////////////////////// - if (widgetMetaData?.defaultValues?.has("tableName")) + if (widgetData?.tableName) { - formValues["tableName"] = widgetMetaData?.defaultValues.get("tableName"); + formValues["tableName"] = widgetData?.tableName; } return ; diff --git a/src/qqq/components/query/BasicAndAdvancedQueryControls.tsx b/src/qqq/components/query/BasicAndAdvancedQueryControls.tsx index 2f45a95..f5d82c8 100644 --- a/src/qqq/components/query/BasicAndAdvancedQueryControls.tsx +++ b/src/qqq/components/query/BasicAndAdvancedQueryControls.tsx @@ -79,6 +79,8 @@ interface BasicAndAdvancedQueryControlsProps queryScreenUsage: QueryScreenUsage; + allowVariables?: boolean; + mode: string; setMode: (mode: string) => void; } @@ -676,6 +678,7 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo return (); diff --git a/src/qqq/components/query/CustomFilterPanel.tsx b/src/qqq/components/query/CustomFilterPanel.tsx index 10e48f2..ded1bd0 100644 --- a/src/qqq/components/query/CustomFilterPanel.tsx +++ b/src/qqq/components/query/CustomFilterPanel.tsx @@ -179,6 +179,7 @@ export const CustomFilterPanel = forwardRef( updateCriteria={(newCriteria, needDebounce) => updateCriteria(newCriteria, index, needDebounce)} removeCriteria={() => removeCriteria(index)} updateBooleanOperator={(newValue) => updateBooleanOperator(newValue)} + allowVariables={props.allowVariables} queryScreenUsage={props.queryScreenUsage} /> {/*JSON.stringify(criteria)*/} diff --git a/src/qqq/components/query/FilterCriteriaRow.tsx b/src/qqq/components/query/FilterCriteriaRow.tsx index 2b4ad63..a180a1e 100644 --- a/src/qqq/components/query/FilterCriteriaRow.tsx +++ b/src/qqq/components/query/FilterCriteriaRow.tsx @@ -199,6 +199,7 @@ interface FilterCriteriaRowProps removeCriteria: () => void; updateBooleanOperator: (newValue: string) => void; queryScreenUsage?: QueryScreenUsage; + allowVariables?: boolean; } FilterCriteriaRow.defaultProps = @@ -267,7 +268,7 @@ export function validateCriteria(criteria: QFilterCriteria, operatorSelectedValu return {criteriaIsValid, criteriaStatusTooltip}; } -export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria, booleanOperator, updateCriteria, removeCriteria, updateBooleanOperator, queryScreenUsage}: FilterCriteriaRowProps): JSX.Element +export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria, booleanOperator, updateCriteria, removeCriteria, updateBooleanOperator, queryScreenUsage, allowVariables}: FilterCriteriaRowProps): JSX.Element { // console.log(`FilterCriteriaRow: criteria: ${JSON.stringify(criteria)}`); const [operatorSelectedValue, setOperatorSelectedValue] = useState(null as OperatorOption); @@ -516,6 +517,7 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria, table={fieldTable} valueChangeHandler={(event, valueIndex, newValue) => handleValueChange(event, valueIndex, newValue)} queryScreenUsage={queryScreenUsage} + allowVariables={allowVariables} /> diff --git a/src/qqq/components/query/FilterCriteriaRowValues.tsx b/src/qqq/components/query/FilterCriteriaRowValues.tsx index eb41a7e..ecd8840 100644 --- a/src/qqq/components/query/FilterCriteriaRowValues.tsx +++ b/src/qqq/components/query/FilterCriteriaRowValues.tsx @@ -39,7 +39,7 @@ import FilterCriteriaPaster from "qqq/components/query/FilterCriteriaPaster"; import {OperatorOption, ValueMode} from "qqq/components/query/FilterCriteriaRow"; import {QueryScreenUsage} from "qqq/pages/records/query/RecordQuery"; import ValueUtils from "qqq/utils/qqq/ValueUtils"; -import React, {SyntheticEvent, useReducer, useState} from "react"; +import React, {SyntheticEvent, useReducer} from "react"; interface Props { @@ -50,6 +50,7 @@ interface Props valueChangeHandler: (event: React.ChangeEvent | SyntheticEvent, valueIndex?: number | "all", newValue?: any) => void; initiallyOpenMultiValuePvs?: boolean; queryScreenUsage?: QueryScreenUsage; + allowVariables?: boolean; } FilterCriteriaRowValues.defaultProps = @@ -187,10 +188,9 @@ export const makeTextField = (field: QFieldMetaData, criteria: QFilterCriteriaWi }; -function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueChangeHandler, initiallyOpenMultiValuePvs, queryScreenUsage}: Props): JSX.Element +function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueChangeHandler, initiallyOpenMultiValuePvs, queryScreenUsage, allowVariables}: Props): JSX.Element { const [, forceUpdate] = useReducer((x) => x + 1, 0); - const [allowVariables, setAllowVariables] = useState(queryScreenUsage == "reportSetup"); if (!operatorOption) { diff --git a/src/qqq/components/query/QuickFilter.tsx b/src/qqq/components/query/QuickFilter.tsx index 60e0cbf..5d666c9 100644 --- a/src/qqq/components/query/QuickFilter.tsx +++ b/src/qqq/components/query/QuickFilter.tsx @@ -52,6 +52,7 @@ interface QuickFilterProps defaultOperator?: QCriteriaOperator; handleRemoveQuickFilterField?: (fieldName: string) => void; queryScreenUsage?: QueryScreenUsage; + allowVariables?: boolean; } QuickFilter.defaultProps = @@ -141,7 +142,7 @@ const getOperatorSelectedValue = (operatorOptions: OperatorOption[], criteria: Q ** Component to render a QuickFilter - that is - a button, with a Menu under it, ** with Operator and Value controls. *******************************************************************************/ -export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData, criteriaParam, updateCriteria, defaultOperator, handleRemoveQuickFilterField, queryScreenUsage}: QuickFilterProps): JSX.Element +export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData, criteriaParam, updateCriteria, defaultOperator, handleRemoveQuickFilterField, queryScreenUsage, allowVariables}: QuickFilterProps): JSX.Element { const operatorOptions = fieldMetaData ? getOperatorOptions(tableMetaData, fullFieldName) : []; const [_, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fullFieldName); @@ -549,6 +550,7 @@ export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData criteria={criteria} field={fieldMetaData} table={tableForField} + allowVariables={allowVariables} valueChangeHandler={(event, valueIndex, newValue) => handleValueChange(event, valueIndex, newValue)} initiallyOpenMultiValuePvs={true} // todo - maybe not? /> diff --git a/src/qqq/components/widgets/DashboardWidgets.tsx b/src/qqq/components/widgets/DashboardWidgets.tsx index edcf070..f2d1dc0 100644 --- a/src/qqq/components/widgets/DashboardWidgets.tsx +++ b/src/qqq/components/widgets/DashboardWidgets.tsx @@ -599,8 +599,8 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco } { widgetMetaData.type === "filterAndColumnsSetup" && ( - widgetData && widgetData[i] && widgetData[i].queryParams && - + widgetData && widgetData[i] && + { }} /> ) diff --git a/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx b/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx index 9834cd2..5800575 100644 --- a/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx +++ b/src/qqq/components/widgets/misc/FilterAndColumnsSetupWidget.tsx @@ -48,6 +48,7 @@ interface FilterAndColumnsSetupWidgetProps { isEditable: boolean; widgetMetaData: QWidgetMetaData; + widgetData: any; recordValues: { [name: string]: any }; onSaveCallback?: (values: { [name: string]: any }) => void; } @@ -82,10 +83,10 @@ const qController = Client.getInstance(); /******************************************************************************* ** Component for editing the main setup of a report - that is: filter & columns *******************************************************************************/ -export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, recordValues, onSaveCallback}: FilterAndColumnsSetupWidgetProps): JSX.Element +export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, widgetData, recordValues, onSaveCallback}: FilterAndColumnsSetupWidgetProps): JSX.Element { const [modalOpen, setModalOpen] = useState(false); - const [hideColumns, setHideColumns] = useState(widgetMetaData?.defaultValues?.has("hideColumns") && widgetMetaData?.defaultValues?.get("hideColumns")); + const [hideColumns, setHideColumns] = useState(widgetData?.hideColumns); const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData); const [alertContent, setAlertContent] = useState(null as string); @@ -107,7 +108,7 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, let columns: QQueryColumns = null; let usingDefaultEmptyFilter = false; let queryFilter = recordValues["queryFilterJson"] && JSON.parse(recordValues["queryFilterJson"]) as QQueryFilter; - const defaultFilterFields = getDefaultFilterFieldNames(widgetMetaData); + const defaultFilterFields = widgetData?.filterDefaultFieldNames; if (!queryFilter) { queryFilter = new QQueryFilter(); @@ -153,7 +154,7 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, //////////////////////////////////////////////////////////////////////////////////////// // if a default table name specified, use it, otherwise use it from the record values // //////////////////////////////////////////////////////////////////////////////////////// - let tableName = widgetMetaData?.defaultValues?.get("tableName"); + let tableName = widgetData?.tableName; if (!tableName && recordValues["tableName"] && (tableMetaData == null || tableMetaData.name != recordValues["tableName"])) { tableName = recordValues["tableName"]; @@ -174,27 +175,13 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, }, [JSON.stringify(recordValues)]); - /******************************************************************************* - ** - *******************************************************************************/ - function getDefaultFilterFieldNames(widgetMetaData: QWidgetMetaData) - { - if (widgetMetaData?.defaultValues?.has("filterDefaultFieldNames")) - { - return (widgetMetaData.defaultValues.get("filterDefaultFieldNames").split(",")); - } - - return ([]); - } - - /******************************************************************************* ** *******************************************************************************/ function openEditor() { let missingRequiredFields = [] as string[]; - getDefaultFilterFieldNames(widgetMetaData)?.forEach((fieldName: string) => + widgetData?.filterDefaultFieldNames?.forEach((fieldName: string) => { if (!recordValues[fieldName]) { @@ -430,6 +417,7 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, } { tableMetaData && ** ** Yuge component. The best. Lots of very smart people are saying so. *******************************************************************************/ -const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, initialColumns}: Props, ref) => +const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQueryFilter, initialColumns}: Props, ref) => { const tableName = table.name; const [searchParams] = useSearchParams(); @@ -2884,6 +2885,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init gridApiRef={gridApiRef} mode={mode} queryScreenUsage={usage} + allowVariables={allowVariables} setMode={doSetMode} savedViewsComponent={savedViewsComponent} columnMenuComponent={buildColumnMenu()} @@ -2912,6 +2914,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init metaData: metaData, queryFilter: queryFilter, updateFilter: doSetQueryFilter, + allowVariables: allowVariables } }} localeText={{