Compare commits

..

3 Commits

14 changed files with 125 additions and 216 deletions

View File

@ -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<readonly QPossibleValue[]>([]);
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,24 +289,23 @@ 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 ? <Icon>{iconName}</Icon> : null;
content = (<Chip label={option.label} color={color} icon={iconElement} size="small" variant="outlined" sx={{fontWeight: 500}} />);
}
}
}
catch (e)
{
}
catch(e)
{ }
if (isMultiple)
if(isMultiple)
{
content = (
<>
@ -328,7 +327,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa
{content}
</li>
);
};
}
const bulkEditSwitchChanged = () =>
{
@ -358,7 +357,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("");
@ -371,19 +370,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}
@ -447,8 +446,7 @@ 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,
@ -467,7 +465,7 @@ function DynamicSelect({tableName, processName, fieldName, possibleValueSourceNa
else
{
return (
<Box>
<Box mb={1.5}>
{autocomplete}
</Box>
);

View File

@ -396,16 +396,15 @@ 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 (widgetData?.tableName)
if (widgetMetaData?.defaultValues?.has("tableName"))
{
formValues["tableName"] = widgetData?.tableName;
formValues["tableName"] = widgetMetaData?.defaultValues.get("tableName");
}
return <FilterAndColumnsSetupWidget
key={formValues["tableName"]} // todo, is this good? it was added so that editing values actually re-renders...
isEditable={true}
widgetMetaData={widgetMetaData}
widgetData={widgetData}
recordValues={formValues}
onSaveCallback={setFormFieldValuesFromWidget}
/>;

View File

@ -63,7 +63,7 @@ function QBreadcrumbs({icon, title, route, light}: Props): JSX.Element
///////////////////////////////////////////////////////////////////////
// strip away empty elements of the route (e.g., trailing slash(es)) //
///////////////////////////////////////////////////////////////////////
if (route.length)
if(route.length)
{
// @ts-ignore
route = route.filter(r => r != "");
@ -74,18 +74,18 @@ function QBreadcrumbs({icon, title, route, light}: Props): JSX.Element
const fullPathToLabel = (fullPath: string, route: string): string =>
{
if (fullPath.endsWith("/"))
if(fullPath.endsWith("/"))
{
fullPath = fullPath.replace(/\/+$/, "");
}
if (pathToLabelMap && pathToLabelMap[fullPath])
if(pathToLabelMap && pathToLabelMap[fullPath])
{
return pathToLabelMap[fullPath];
}
return (routeToLabel(route));
};
}
let pageTitle = branding?.appName ?? "";
const fullRoutes: string[] = [];
@ -94,9 +94,9 @@ function QBreadcrumbs({icon, title, route, light}: Props): JSX.Element
{
////////////////////////////////////////////////////////
// avoid showing "saved view" as a breadcrumb element //
// e.g., if at /app/table/savedView/1 //
// e.g., if at /app/table/savedView/1 (so where i==2) //
////////////////////////////////////////////////////////
if (routes[i] === "savedView" && i == routes.length - 1)
if(routes[i] === "savedView" && i == 2)
{
continue;
}
@ -106,12 +106,12 @@ function QBreadcrumbs({icon, title, route, light}: Props): JSX.Element
// e.g., when at /app/table/savedView/1 (so where i==1) //
// we want to just be showing "App" //
///////////////////////////////////////////////////////////////////////
if (i < routes.length - 1 && routes[i + 1] == "savedView" && i == 1)
if(i < routes.length - 1 && routes[i+1] == "savedView" && i == 1)
{
continue;
}
if (routes[i] === "")
if(routes[i] === "")
{
continue;
}

View File

@ -19,15 +19,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Popper, InputAdornment, Box} from "@mui/material";
import {Popper, InputAdornment} from "@mui/material";
import AppBar from "@mui/material/AppBar";
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 ListItemIcon from "@mui/material/ListItemIcon";
import TextField from "@mui/material/TextField";
import Toolbar from "@mui/material/Toolbar";
import React, {useContext, useEffect, useRef, useState} from "react";
import React, {useContext, useEffect, useState} from "react";
import {useLocation, useNavigate} from "react-router-dom";
import QContext from "QContext";
import QBreadcrumbs, {routeToLabel} from "qqq/components/horseshoe/Breadcrumbs";
@ -44,8 +45,7 @@ interface Props
isMini?: boolean;
}
interface HistoryEntry
{
interface HistoryEntry {
id: number;
path: string;
label: string;
@ -64,7 +64,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const route = useLocation().pathname.split("/").slice(1);
const navigate = useNavigate();
const {pageHeader, setDotMenuOpen} = useContext(QContext);
const {pageHeader} = useContext(QContext);
useEffect(() =>
{
@ -99,7 +99,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const options = [] as any;
history.entries.reverse().forEach((entry, index) =>
options.push({label: `${entry.label} index`, id: index, key: index, path: entry.path, iconName: entry.iconName})
);
)
setHistory(options);
// Remove event listener on cleanup
@ -111,7 +111,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const goToHistory = (path: string) =>
{
navigate(path);
};
}
function buildHistoryEntries()
{
@ -119,7 +119,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const options = [] as any;
history.entries.reverse().forEach((entry, index) =>
options.push({label: entry.label, id: index, key: index, path: entry.path, iconName: entry.iconName})
);
)
setHistory(options);
}
@ -133,12 +133,12 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const handleAutocompleteOnChange = (event: any, value: any, reason: any, details: any) =>
{
if (value)
if(value)
{
goToHistory(value.path);
}
setAutocompleteValue(null);
};
}
const CustomPopper = function (props: any)
{
@ -146,8 +146,8 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
{...props}
style={{whiteSpace: "nowrap", width: "auto"}}
placement="bottom-end"
/>);
};
/>)
}
const renderHistory = () =>
{
@ -166,7 +166,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
PopperComponent={CustomPopper}
isOptionEqualToValue={(option, value) => option.id === value.id}
sx={recentlyViewedMenu}
renderInput={(params) => <TextField {...params} label="Recently Viewed Records" InputProps={{
renderInput={(params) => <TextField {...params} label="Recently Viewed Records" InputProps={{
...params.InputProps,
endAdornment: (
<InputAdornment position="end">
@ -184,7 +184,7 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
)}
/>
);
};
}
// Styles for the navbar icons
const iconsStyle = ({
@ -210,18 +210,18 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
const {pathToLabelMap} = useContext(QContext);
const fullPathToLabel = (fullPath: string, route: string): string =>
{
if (fullPath.endsWith("/"))
if(fullPath.endsWith("/"))
{
fullPath = fullPath.replace(/\/+$/, "");
}
if (pathToLabelMap && pathToLabelMap[fullPath])
if(pathToLabelMap && pathToLabelMap[fullPath])
{
return pathToLabelMap[fullPath];
}
return (routeToLabel(route));
};
}
const breadcrumbTitle = fullPathToLabel(fullPath, route[route.length - 1]);
@ -242,14 +242,9 @@ function NavBar({absolute, light, isMini}: Props): JSX.Element
</Box>
{isMini ? null : (
<Box sx={(theme) => navbarRow(theme, {isMini})}>
<Box mt={"-0.25rem"} pb={"0.75rem"} pr={2} mr={-2} sx={{"& *": {cursor: "pointer !important"}}}>
<Box pr={0} mr={-2}>
{renderHistory()}
</Box>
<Box mt={"-1rem"}>
<IconButton size="small" disableRipple color="inherit" onClick={() => setDotMenuOpen(true)}>
<Icon sx={iconsStyle} fontSize="small">search</Icon>
</IconButton>
</Box>
</Box>
)}
</Toolbar>

View File

@ -79,8 +79,6 @@ interface BasicAndAdvancedQueryControlsProps
queryScreenUsage: QueryScreenUsage;
allowVariables?: boolean;
mode: string;
setMode: (mode: string) => void;
}
@ -678,7 +676,6 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
return (<QuickFilter
key={fieldName}
allowVariables={props.allowVariables}
fullFieldName={fieldName}
tableMetaData={tableMetaData}
updateCriteria={updateQuickCriteria}
@ -704,7 +701,6 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
updateCriteria={updateQuickCriteria}
criteriaParam={getQuickCriteriaParam(fieldName)}
fieldMetaData={field}
allowVariables={props.allowVariables}
defaultOperator={defaultOperator}
queryScreenUsage={queryScreenUsage}
handleRemoveQuickFilterField={handleRemoveQuickFilterField} />);

View File

@ -179,7 +179,6 @@ export const CustomFilterPanel = forwardRef<any, GridFilterPanelProps>(
updateCriteria={(newCriteria, needDebounce) => updateCriteria(newCriteria, index, needDebounce)}
removeCriteria={() => removeCriteria(index)}
updateBooleanOperator={(newValue) => updateBooleanOperator(newValue)}
allowVariables={props.allowVariables}
queryScreenUsage={props.queryScreenUsage}
/>
{/*JSON.stringify(criteria)*/}

View File

@ -199,7 +199,6 @@ interface FilterCriteriaRowProps
removeCriteria: () => void;
updateBooleanOperator: (newValue: string) => void;
queryScreenUsage?: QueryScreenUsage;
allowVariables?: boolean;
}
FilterCriteriaRow.defaultProps =
@ -268,7 +267,7 @@ export function validateCriteria(criteria: QFilterCriteria, operatorSelectedValu
return {criteriaIsValid, criteriaStatusTooltip};
}
export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria, booleanOperator, updateCriteria, removeCriteria, updateBooleanOperator, queryScreenUsage, allowVariables}: FilterCriteriaRowProps): JSX.Element
export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria, booleanOperator, updateCriteria, removeCriteria, updateBooleanOperator, queryScreenUsage}: FilterCriteriaRowProps): JSX.Element
{
// console.log(`FilterCriteriaRow: criteria: ${JSON.stringify(criteria)}`);
const [operatorSelectedValue, setOperatorSelectedValue] = useState(null as OperatorOption);
@ -517,7 +516,6 @@ export function FilterCriteriaRow({id, index, tableMetaData, metaData, criteria,
table={fieldTable}
valueChangeHandler={(event, valueIndex, newValue) => handleValueChange(event, valueIndex, newValue)}
queryScreenUsage={queryScreenUsage}
allowVariables={allowVariables}
/>
</Box>
<Box display="inline-block">

View File

@ -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} from "react";
import React, {SyntheticEvent, useReducer, useState} from "react";
interface Props
{
@ -50,7 +50,6 @@ interface Props
valueChangeHandler: (event: React.ChangeEvent | SyntheticEvent, valueIndex?: number | "all", newValue?: any) => void;
initiallyOpenMultiValuePvs?: boolean;
queryScreenUsage?: QueryScreenUsage;
allowVariables?: boolean;
}
FilterCriteriaRowValues.defaultProps =
@ -188,9 +187,10 @@ export const makeTextField = (field: QFieldMetaData, criteria: QFilterCriteriaWi
};
function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueChangeHandler, initiallyOpenMultiValuePvs, queryScreenUsage, allowVariables}: Props): JSX.Element
function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueChangeHandler, initiallyOpenMultiValuePvs, queryScreenUsage}: Props): JSX.Element
{
const [, forceUpdate] = useReducer((x) => x + 1, 0);
const [allowVariables, setAllowVariables] = useState(queryScreenUsage == "reportSetup");
if (!operatorOption)
{
@ -320,7 +320,7 @@ function FilterCriteriaRowValues({operatorOption, criteria, field, table, valueC
initialValues = criteria.values;
}
}
return <Box>
return <Box mb={-1.5}>
<DynamicSelect
tableName={table.name}
fieldName={field.name}

View File

@ -52,7 +52,6 @@ interface QuickFilterProps
defaultOperator?: QCriteriaOperator;
handleRemoveQuickFilterField?: (fieldName: string) => void;
queryScreenUsage?: QueryScreenUsage;
allowVariables?: boolean;
}
QuickFilter.defaultProps =
@ -142,7 +141,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, allowVariables}: QuickFilterProps): JSX.Element
export default function QuickFilter({tableMetaData, fullFieldName, fieldMetaData, criteriaParam, updateCriteria, defaultOperator, handleRemoveQuickFilterField, queryScreenUsage}: QuickFilterProps): JSX.Element
{
const operatorOptions = fieldMetaData ? getOperatorOptions(tableMetaData, fullFieldName) : [];
const [_, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fullFieldName);
@ -550,7 +549,6 @@ 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?
/>

View File

@ -599,8 +599,8 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
}
{
widgetMetaData.type === "filterAndColumnsSetup" && (
widgetData && widgetData[i] &&
<FilterAndColumnsSetupWidget isEditable={false} widgetMetaData={widgetMetaData} widgetData={widgetData[i]} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
widgetData && widgetData[i] && widgetData[i].queryParams &&
<FilterAndColumnsSetupWidget isEditable={false} widgetMetaData={widgetMetaData} recordValues={convertQRecordValuesFromMapToObject(record)} onSaveCallback={() =>
{
}} />
)

View File

@ -48,7 +48,6 @@ interface FilterAndColumnsSetupWidgetProps
{
isEditable: boolean;
widgetMetaData: QWidgetMetaData;
widgetData: any;
recordValues: { [name: string]: any };
onSaveCallback?: (values: { [name: string]: any }) => void;
}
@ -83,10 +82,10 @@ const qController = Client.getInstance();
/*******************************************************************************
** Component for editing the main setup of a report - that is: filter & columns
*******************************************************************************/
export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, widgetData, recordValues, onSaveCallback}: FilterAndColumnsSetupWidgetProps): JSX.Element
export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData, recordValues, onSaveCallback}: FilterAndColumnsSetupWidgetProps): JSX.Element
{
const [modalOpen, setModalOpen] = useState(false);
const [hideColumns, setHideColumns] = useState(widgetData?.hideColumns);
const [hideColumns, setHideColumns] = useState(widgetMetaData?.defaultValues?.has("hideColumns") && widgetMetaData?.defaultValues?.get("hideColumns"));
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
const [alertContent, setAlertContent] = useState(null as string);
@ -108,7 +107,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 = widgetData?.filterDefaultFieldNames;
const defaultFilterFields = getDefaultFilterFieldNames(widgetMetaData);
if (!queryFilter)
{
queryFilter = new QQueryFilter();
@ -154,7 +153,7 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData,
////////////////////////////////////////////////////////////////////////////////////////
// if a default table name specified, use it, otherwise use it from the record values //
////////////////////////////////////////////////////////////////////////////////////////
let tableName = widgetData?.tableName;
let tableName = widgetMetaData?.defaultValues?.get("tableName");
if (!tableName && recordValues["tableName"] && (tableMetaData == null || tableMetaData.name != recordValues["tableName"]))
{
tableName = recordValues["tableName"];
@ -175,13 +174,27 @@ 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[];
widgetData?.filterDefaultFieldNames?.forEach((fieldName: string) =>
getDefaultFilterFieldNames(widgetMetaData)?.forEach((fieldName: string) =>
{
if (!recordValues[fieldName])
{
@ -417,7 +430,6 @@ export default function FilterAndColumnsSetupWidget({isEditable, widgetMetaData,
}
{
tableMetaData && <RecordQuery
allowVariables={widgetData?.allowVariables}
ref={recordQueryRef}
table={tableMetaData}
usage="reportSetup"

View File

@ -33,7 +33,6 @@ import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJo
import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError";
import {QJobRunning} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobRunning";
import {QJobStarted} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobStarted";
import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
import {Alert, Box, Button, CircularProgress, Icon, TablePagination} from "@mui/material";
@ -97,8 +96,6 @@ let formikSetFieldValueFunction = (field: string, value: any, shouldValidate?: b
{
};
const cachedPossibleValueLabels: { [fieldName: string]: { [id: string | number]: string } } = {};
function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, isReport, recordIds, closeModalHandler, forceReInit, overrideLabel}: Props): JSX.Element
{
const processNameParam = useParams().processName;
@ -446,20 +443,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
{
if (processValues[key])
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if we have a cached possible-value label for this field name (key), then set it as the PV's initialDisplayValue //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (cachedPossibleValueLabels[key] && cachedPossibleValueLabels[key][processValues[key]])
{
formFields[key].possibleValueProps.initialDisplayValue = cachedPossibleValueLabels[key][processValues[key]];
}
else
{
////////////////////////////////////////////////////////////////////////////
// else (and i don't think this should happen?) at least set something... //
////////////////////////////////////////////////////////////////////////////
formFields[key].possibleValueProps.initialDisplayValue = processValues[key];
}
formFields[key].possibleValueProps.initialDisplayValue = processValues[key];
}
formFields[key].possibleValueProps.otherValues = formFields[key].possibleValueProps.otherValues ?? new Map<string, any>();
@ -881,12 +865,6 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
{
dynamicFormFields[fieldName] = dynamicFormValue;
initialValues[fieldName] = initialValue;
if (formikSetFieldValueFunction)
{
formikSetFieldValueFunction(fieldName, initialValue);
}
formValidations[fieldName] = validation;
};
@ -936,11 +914,6 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
fullFieldList.forEach((field) =>
{
initialValues[field.name] = processValues[field.name];
if (formikSetFieldValueFunction)
{
formikSetFieldValueFunction(field.name, processValues[field.name]);
}
});
////////////////////////////////////////////////////////////////////////////////////
@ -1100,88 +1073,40 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
if (lastProcessResponse instanceof QJobComplete)
{
///////////////////////////////////////////////////////////////////////////////////////////////
// run an async function here, in case we need to await looking up any possible-value labels //
///////////////////////////////////////////////////////////////////////////////////////////////
(async () =>
const qJobComplete = lastProcessResponse as QJobComplete;
setJobUUID(null);
setNewStep(qJobComplete.nextStep);
setProcessValues(qJobComplete.values);
setQJobRunning(null);
if (formikSetFieldValueFunction)
{
const qJobComplete = lastProcessResponse as QJobComplete;
const newValues = qJobComplete.values;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the process step sent a new frontend-step-list, then refresh what we have in state (constructing new full model objects) //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let frontendSteps = steps;
const updatedFrontendStepList = qJobComplete.updatedFrontendStepList;
if (updatedFrontendStepList)
//////////////////////////////////
// reset field values in formik //
//////////////////////////////////
for (let key in qJobComplete.values)
{
setSteps(updatedFrontendStepList);
frontendSteps = updatedFrontendStepList;
}
///////////////////////////////////////////////////////////////////////////////////
// if the next screen has any PVS fields - look up their labels (display values) //
///////////////////////////////////////////////////////////////////////////////////
const nextStepName = qJobComplete.nextStep;
let nextStep: QFrontendStepMetaData | null = null;
if (frontendSteps && nextStepName)
{
for (let i = 0; i < frontendSteps.length; i++)
if (Object.hasOwn(formFields, key))
{
if (frontendSteps[i].name === nextStepName)
{
nextStep = frontendSteps[i];
break;
}
}
if (nextStep && nextStep.formFields)
{
for (let i = 0; i < nextStep.formFields.length; i++)
{
const field = nextStep.formFields[i];
const fieldName = field.name;
if (field.possibleValueSourceName && newValues && newValues[fieldName])
{
const results: QPossibleValue[] = await Client.getInstance().possibleValues(null, processName, fieldName, null, [newValues[fieldName]]);
if (results && results.length > 0)
{
if (!cachedPossibleValueLabels[fieldName])
{
cachedPossibleValueLabels[fieldName] = {};
}
cachedPossibleValueLabels[fieldName][newValues[fieldName]] = results[0].label;
}
}
}
console.log(`(re)setting form field [${key}] to [${qJobComplete.values[key]}]`);
formikSetFieldValueFunction(key, qJobComplete.values[key]);
}
}
}
setJobUUID(null);
setNewStep(nextStepName);
setProcessValues(newValues);
setQJobRunning(null);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the process step sent a new frontend-step-list, then refresh what we have in state (constructing new full model objects) //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const updatedFrontendStepList = qJobComplete.updatedFrontendStepList;
if (updatedFrontendStepList)
{
setSteps(updatedFrontendStepList);
}
if (formikSetFieldValueFunction)
{
//////////////////////////////////
// reset field values in formik //
//////////////////////////////////
for (let key in qJobComplete.values)
{
if (Object.hasOwn(formFields, key))
{
console.log(`(re)setting form field [${key}] to [${qJobComplete.values[key]}]`);
formikSetFieldValueFunction(key, qJobComplete.values[key]);
}
}
}
if (activeStep && activeStep.recordListFields)
{
setNeedRecords(true);
}
})();
if (activeStep && activeStep.recordListFields)
{
setNeedRecords(true);
}
}
else if (lastProcessResponse instanceof QJobStarted)
{
@ -1646,7 +1571,7 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
);
const body = (
<Box py={3} mb={20} className="processRun">
<Box py={3} mb={20}>
<Grid container justifyContent="center" alignItems="center" sx={{height: "100%", mt: 8}}>
<Grid item xs={12} lg={10} xl={8}>
{form}

View File

@ -94,7 +94,6 @@ interface Props
isModal?: boolean;
initialQueryFilter?: QQueryFilter;
initialColumns?: QQueryColumns;
allowVariables?: boolean;
}
///////////////////////////////////////////////////////
@ -126,7 +125,7 @@ const getLoadingScreen = (isModal: boolean) =>
**
** Yuge component. The best. Lots of very smart people are saying so.
*******************************************************************************/
const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQueryFilter, initialColumns}: Props, ref) =>
const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, initialColumns}: Props, ref) =>
{
const tableName = table.name;
const [searchParams] = useSearchParams();
@ -631,7 +630,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQ
const type = (e.target as any).type;
const validType = (type !== "text" && type !== "textarea" && type !== "input" && type !== "search");
if (validType && !isModal && !dotMenuOpen && !keyboardHelpOpen && !activeModalProcess)
if (validType && !dotMenuOpen && !keyboardHelpOpen && !activeModalProcess)
{
if (!e.metaKey && !e.ctrlKey && e.key === "n" && table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission)
{
@ -669,7 +668,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQ
{
document.removeEventListener("keydown", down);
};
}, [isModal, dotMenuOpen, keyboardHelpOpen, metaData, activeModalProcess]);
}, [dotMenuOpen, keyboardHelpOpen, metaData, activeModalProcess]);
/*******************************************************************************
@ -2885,7 +2884,6 @@ const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQ
gridApiRef={gridApiRef}
mode={mode}
queryScreenUsage={usage}
allowVariables={allowVariables}
setMode={doSetMode}
savedViewsComponent={savedViewsComponent}
columnMenuComponent={buildColumnMenu()}
@ -2914,7 +2912,6 @@ const RecordQuery = forwardRef(({table, usage, isModal, allowVariables, initialQ
metaData: metaData,
queryFilter: queryFilter,
updateFilter: doSetQueryFilter,
allowVariables: allowVariables
}
}}
localeText={{

View File

@ -717,7 +717,6 @@ input[type="search"]::-webkit-search-results-decoration
background-color: #0062FF !important;
}
/* several styles below here for user-defined alert inside helpContent */
.helpContentAlert
{
padding: 6px 16px;
@ -780,10 +779,3 @@ input[type="search"]::-webkit-search-results-decoration
{
color: #F44335;
}
/* the alert widget, was built with minimal (no?) margins, for embedding in
a parent widget; but for using it on a process, give it some breathing room */
.processRun .widget .MuiAlert-root
{
margin: 2rem 1rem;
}