mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
CE-1115 Fix so that record query popup actually shows the filter & columns that are on the report edit screen... fix filters saved w/ record to be prep'ed for backend; refactor that prepForBackend method out of RecordQuery, into FilterUtils; update recordQuery to be a better manager of counts (showing when counting after the initial load, plus not always re-counting (e.g., when paginating)
This commit is contained in:
@ -86,11 +86,17 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
|
|
||||||
const [alertContent, setAlertContent] = useState(null as string);
|
const [alertContent, setAlertContent] = useState(null as string);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// we'll actually keep 2 copies of the query filter around here - //
|
||||||
|
// the one in the record (as json) is one that the backend likes (e.g., possible values as ids) //
|
||||||
|
// this "frontend" one is one that the frontend can use (possible values as objects w/ labels). //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const [frontendQueryFilter, setFrontendQueryFilter] = useState(null as QQueryFilter);
|
||||||
|
|
||||||
const {helpHelpActive} = useContext(QContext);
|
const {helpHelpActive} = useContext(QContext);
|
||||||
|
|
||||||
const recordQueryRef = useRef();
|
const recordQueryRef = useRef();
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// load values from record //
|
// load values from record //
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
@ -100,10 +106,10 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
queryFilter = new QQueryFilter();
|
queryFilter = new QQueryFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
let columns = recordValues["columnsJson"] && JSON.parse(recordValues["columnsJson"]) as QQueryColumns;
|
let columns: QQueryColumns = null;
|
||||||
if(!columns)
|
if(recordValues["columnsJson"])
|
||||||
{
|
{
|
||||||
columns = new QQueryColumns();
|
columns = QQueryColumns.buildFromJSON(recordValues["columnsJson"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -117,6 +123,10 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
{
|
{
|
||||||
const tableMetaData = await qController.loadTableMetaData(recordValues["tableName"])
|
const tableMetaData = await qController.loadTableMetaData(recordValues["tableName"])
|
||||||
setTableMetaData(tableMetaData);
|
setTableMetaData(tableMetaData);
|
||||||
|
|
||||||
|
const queryFilterForFrontend = Object.assign({}, queryFilter);
|
||||||
|
await FilterUtils.cleanupValuesInFilerFromQueryString(qController, tableMetaData, queryFilterForFrontend)
|
||||||
|
setFrontendQueryFilter(queryFilterForFrontend)
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}, [recordValues]);
|
}, [recordValues]);
|
||||||
@ -150,7 +160,14 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
|
|
||||||
view.queryColumns.sortColumnsFixingPinPositions();
|
view.queryColumns.sortColumnsFixingPinPositions();
|
||||||
|
|
||||||
onSaveCallback({queryFilterJson: JSON.stringify(view.queryFilter), columnsJson: JSON.stringify(view.queryColumns)});
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// keep the query filter that came from the recordQuery screen as the front-end version (w/ possible value objects) //
|
||||||
|
// but prep a copy of it for the backend, to stringify as json in the record being edited //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
setFrontendQueryFilter(view.queryFilter);
|
||||||
|
const filter = FilterUtils.prepQueryFilterForBackend(tableMetaData, view.queryFilter);
|
||||||
|
|
||||||
|
onSaveCallback({queryFilterJson: JSON.stringify(filter), columnsJson: JSON.stringify(view.queryColumns)});
|
||||||
|
|
||||||
closeEditor();
|
closeEditor();
|
||||||
}
|
}
|
||||||
@ -197,7 +214,7 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
{
|
{
|
||||||
if(tableMetaData)
|
if(tableMetaData)
|
||||||
{
|
{
|
||||||
if(queryFilter?.criteria?.length > 0 || queryFilter?.subFilters?.length > 0)
|
if(frontendQueryFilter?.criteria?.length > 0 || frontendQueryFilter?.subFilters?.length > 0)
|
||||||
{
|
{
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
@ -271,7 +288,7 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
<h5>Query Filter</h5>
|
<h5>Query Filter</h5>
|
||||||
{
|
{
|
||||||
mayShowQueryPreview() &&
|
mayShowQueryPreview() &&
|
||||||
<AdvancedQueryPreview tableMetaData={tableMetaData} queryFilter={queryFilter} isEditable={false} isQueryTooComplex={queryFilter.subFilters?.length > 0} removeCriteriaByIndexCallback={null} />
|
<AdvancedQueryPreview tableMetaData={tableMetaData} queryFilter={frontendQueryFilter} isEditable={false} isQueryTooComplex={frontendQueryFilter.subFilters?.length > 0} removeCriteriaByIndexCallback={null} />
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
!mayShowQueryPreview() &&
|
!mayShowQueryPreview() &&
|
||||||
@ -329,7 +346,10 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
|
|||||||
ref={recordQueryRef}
|
ref={recordQueryRef}
|
||||||
table={tableMetaData}
|
table={tableMetaData}
|
||||||
usage="reportSetup"
|
usage="reportSetup"
|
||||||
isModal={true} />
|
isModal={true}
|
||||||
|
initialQueryFilter={frontendQueryFilter}
|
||||||
|
initialColumns={columns}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
@ -92,6 +92,8 @@ interface Props
|
|||||||
launchProcess?: QProcessMetaData;
|
launchProcess?: QProcessMetaData;
|
||||||
usage?: QueryScreenUsage;
|
usage?: QueryScreenUsage;
|
||||||
isModal?: boolean;
|
isModal?: boolean;
|
||||||
|
initialQueryFilter?: QQueryFilter;
|
||||||
|
initialColumns?: QQueryColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
@ -123,7 +125,7 @@ const getLoadingScreen = (isModal: boolean) =>
|
|||||||
**
|
**
|
||||||
** Yuge component. The best. Lots of very smart people are saying so.
|
** Yuge component. The best. Lots of very smart people are saying so.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, initialColumns}: Props, ref) =>
|
||||||
{
|
{
|
||||||
const tableName = table.name;
|
const tableName = table.name;
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
@ -193,7 +195,9 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
const densityLocalStorageKey = `${DENSITY_LOCAL_STORAGE_KEY_ROOT}`;
|
const densityLocalStorageKey = `${DENSITY_LOCAL_STORAGE_KEY_ROOT}`;
|
||||||
|
|
||||||
// only load things out of local storage on the first render
|
///////////////////////////////////////////////////////////////
|
||||||
|
// only load things out of local storage on the first render //
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
console.log("This is firstRender, so reading defaults from local storage...");
|
console.log("This is firstRender, so reading defaults from local storage...");
|
||||||
@ -224,6 +228,25 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
defaultView.mode = defaultMode;
|
defaultView.mode = defaultMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(firstRender)
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// allow a caller to send in an initial filter & set of columns. //
|
||||||
|
// only to be used on "first render" //
|
||||||
|
// JSON.parse(JSON.stringify()) to do deep clone and keep object clean //
|
||||||
|
// unclear why not needed on initialColumns... //
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
if (initialQueryFilter)
|
||||||
|
{
|
||||||
|
defaultView.queryFilter = JSON.parse(JSON.stringify(initialQueryFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialColumns)
|
||||||
|
{
|
||||||
|
defaultView.queryColumns = initialColumns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// in case the view is missing any of these attributes, give them a reasonable default //
|
// in case the view is missing any of these attributes, give them a reasonable default //
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -431,51 +454,6 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
const prepQueryFilterForBackend = (sourceFilter: QQueryFilter) =>
|
|
||||||
{
|
|
||||||
const filterForBackend = new QQueryFilter([], sourceFilter.orderBys, sourceFilter.subFilters, sourceFilter.booleanOperator);
|
|
||||||
for (let i = 0; i < sourceFilter?.criteria?.length; i++)
|
|
||||||
{
|
|
||||||
const criteria = sourceFilter.criteria[i];
|
|
||||||
const {criteriaIsValid} = validateCriteria(criteria, null);
|
|
||||||
if (criteriaIsValid)
|
|
||||||
{
|
|
||||||
if (criteria.operator == QCriteriaOperator.IS_BLANK || criteria.operator == QCriteriaOperator.IS_NOT_BLANK)
|
|
||||||
{
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// do this to avoid submitting an empty-string argument for blank/not-blank operators... //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
filterForBackend.criteria.push(new QFilterCriteria(criteria.fieldName, criteria.operator, []));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// else push a clone of the criteria - since it may get manipulated below (convertFilterPossibleValuesToIds) //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
const [field] = FilterUtils.getField(tableMetaData, criteria.fieldName);
|
|
||||||
filterForBackend.criteria.push(new QFilterCriteria(criteria.fieldName, criteria.operator, FilterUtils.cleanseCriteriaValueForQQQ(criteria.values, field)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
// recursively prep subfilters as well //
|
|
||||||
/////////////////////////////////////////
|
|
||||||
let subFilters = [] as QQueryFilter[];
|
|
||||||
for (let j = 0; j < sourceFilter?.subFilters?.length; j++)
|
|
||||||
{
|
|
||||||
subFilters.push(prepQueryFilterForBackend(sourceFilter.subFilters[j]));
|
|
||||||
}
|
|
||||||
|
|
||||||
filterForBackend.subFilters = subFilters;
|
|
||||||
filterForBackend.skip = pageNumber * rowsPerPage;
|
|
||||||
filterForBackend.limit = rowsPerPage;
|
|
||||||
return filterForBackend;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@ -507,7 +485,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
totalRecords: totalRecords,
|
totalRecords: totalRecords,
|
||||||
columnsModel: columnsModel,
|
columnsModel: columnsModel,
|
||||||
columnVisibilityModel: columnVisibilityModel,
|
columnVisibilityModel: columnVisibilityModel,
|
||||||
queryFilter: prepQueryFilterForBackend(queryFilter)
|
queryFilter: FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter)
|
||||||
};
|
};
|
||||||
|
|
||||||
exportMenu = (<>
|
exportMenu = (<>
|
||||||
@ -877,7 +855,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** This is the method that actually executes a query to update the data in the table.
|
** This is the method that actually executes a query to update the data in the table.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
const updateTable = (reason?: string) =>
|
const updateTable = (reason?: string, clearOutCount = true) =>
|
||||||
{
|
{
|
||||||
if (pageState != "ready")
|
if (pageState != "ready")
|
||||||
{
|
{
|
||||||
@ -901,7 +879,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
// copy the orderBys & operator into it - but we'll build its criteria one-by-one, //
|
// copy the orderBys & operator into it - but we'll build its criteria one-by-one, //
|
||||||
// as clones, as we'll need to tweak them a bit //
|
// as clones, as we'll need to tweak them a bit //
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter, pageNumber, rowsPerPage);
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// figure out joins to use in the query //
|
// figure out joins to use in the query //
|
||||||
@ -927,6 +905,12 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
console.log(`Issuing query: ${thisQueryId}`);
|
console.log(`Issuing query: ${thisQueryId}`);
|
||||||
if (tableMetaData.capabilities.has(Capability.TABLE_COUNT))
|
if (tableMetaData.capabilities.has(Capability.TABLE_COUNT))
|
||||||
{
|
{
|
||||||
|
if(clearOutCount)
|
||||||
|
{
|
||||||
|
setTotalRecords(null);
|
||||||
|
setDistinctRecords(null);
|
||||||
|
}
|
||||||
|
|
||||||
let includeDistinct = isJoinMany(tableMetaData, getVisibleJoinTables());
|
let includeDistinct = isJoinMany(tableMetaData, getVisibleJoinTables());
|
||||||
qController.count(tableName, filterForBackend, queryJoins, includeDistinct, tableVariant).then(([count, distinctCount]) =>
|
qController.count(tableName, filterForBackend, queryJoins, includeDistinct, tableVariant).then(([count, distinctCount]) =>
|
||||||
{
|
{
|
||||||
@ -1428,7 +1412,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
{
|
{
|
||||||
if (selectFullFilterState === "filter")
|
if (selectFullFilterState === "filter")
|
||||||
{
|
{
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter);
|
||||||
filterForBackend.skip = 0;
|
filterForBackend.skip = 0;
|
||||||
filterForBackend.limit = null;
|
filterForBackend.limit = null;
|
||||||
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(filterForBackend))}`;
|
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(filterForBackend))}`;
|
||||||
@ -1436,7 +1420,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
|
|
||||||
if (selectFullFilterState === "filterSubset")
|
if (selectFullFilterState === "filterSubset")
|
||||||
{
|
{
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter);
|
||||||
filterForBackend.skip = 0;
|
filterForBackend.skip = 0;
|
||||||
filterForBackend.limit = selectionSubsetSize;
|
filterForBackend.limit = selectionSubsetSize;
|
||||||
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(filterForBackend))}`;
|
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(filterForBackend))}`;
|
||||||
@ -1459,14 +1443,14 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
{
|
{
|
||||||
if (selectFullFilterState === "filter")
|
if (selectFullFilterState === "filter")
|
||||||
{
|
{
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter);
|
||||||
filterForBackend.skip = 0;
|
filterForBackend.skip = 0;
|
||||||
filterForBackend.limit = null;
|
filterForBackend.limit = null;
|
||||||
setRecordIdsForProcess(filterForBackend);
|
setRecordIdsForProcess(filterForBackend);
|
||||||
}
|
}
|
||||||
else if (selectFullFilterState === "filterSubset")
|
else if (selectFullFilterState === "filterSubset")
|
||||||
{
|
{
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter);
|
||||||
filterForBackend.skip = 0;
|
filterForBackend.skip = 0;
|
||||||
filterForBackend.limit = selectionSubsetSize;
|
filterForBackend.limit = selectionSubsetSize;
|
||||||
setRecordIdsForProcess(filterForBackend);
|
setRecordIdsForProcess(filterForBackend);
|
||||||
@ -1924,7 +1908,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
const openColumnStatistics = async (column: GridColDef) =>
|
const openColumnStatistics = async (column: GridColDef) =>
|
||||||
{
|
{
|
||||||
setFilterForColumnStats(prepQueryFilterForBackend(queryFilter));
|
setFilterForColumnStats(FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter));
|
||||||
setColumnStatsFieldName(column.field);
|
setColumnStatsFieldName(column.field);
|
||||||
|
|
||||||
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, column.field);
|
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, column.field);
|
||||||
@ -2285,7 +2269,7 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
// to avoid both this useEffect and the one below from both doing an "initial query", //
|
// to avoid both this useEffect and the one below from both doing an "initial query", //
|
||||||
// only run this one if at least 1 query has already been ran //
|
// only run this one if at least 1 query has already been ran //
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
updateTable("useEffect(pageNumber,rowsPerPage)");
|
updateTable("useEffect(pageNumber,rowsPerPage)", false);
|
||||||
}
|
}
|
||||||
}, [pageNumber, rowsPerPage]);
|
}, [pageNumber, rowsPerPage]);
|
||||||
|
|
||||||
@ -2320,7 +2304,16 @@ const RecordQuery = forwardRef(({table, usage, isModal}: Props, ref) =>
|
|||||||
|
|
||||||
if (pageState == "ready")
|
if (pageState == "ready")
|
||||||
{
|
{
|
||||||
const filterForBackend = prepQueryFilterForBackend(queryFilter);
|
const filterForBackend = FilterUtils.prepQueryFilterForBackend(tableMetaData, queryFilter);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// remove the skip & limit (e.g., pagination) from this hash - //
|
||||||
|
// as we have a specific useEffect watching these, specifically //
|
||||||
|
// so we can pass the dont-clear-count flag into updateTable, //
|
||||||
|
// to try to keep the count from flashing back & forth to "Counting" //
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
filterForBackend.skip = null;
|
||||||
|
filterForBackend.limit = null;
|
||||||
|
|
||||||
const newFilterHash = JSON.stringify(filterForBackend);
|
const newFilterHash = JSON.stringify(filterForBackend);
|
||||||
if (filterHash != newFilterHash)
|
if (filterHash != newFilterHash)
|
||||||
@ -2960,6 +2953,8 @@ RecordQuery.defaultProps = {
|
|||||||
usage: "queryScreen",
|
usage: "queryScreen",
|
||||||
launchProcess: null,
|
launchProcess: null,
|
||||||
isModal: false,
|
isModal: false,
|
||||||
|
initialQueryFilter: null,
|
||||||
|
initialColumns: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryF
|
|||||||
import {ThisOrLastPeriodExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/ThisOrLastPeriodExpression";
|
import {ThisOrLastPeriodExpression} from "@kingsrook/qqq-frontend-core/lib/model/query/ThisOrLastPeriodExpression";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import {GridSortModel} from "@mui/x-data-grid-pro";
|
import {GridSortModel} from "@mui/x-data-grid-pro";
|
||||||
|
import {validateCriteria} from "qqq/components/query/FilterCriteriaRow";
|
||||||
import TableUtils from "qqq/utils/qqq/TableUtils";
|
import TableUtils from "qqq/utils/qqq/TableUtils";
|
||||||
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
||||||
|
|
||||||
@ -612,6 +613,58 @@ class FilterUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** make a new query filter, based on the input one, but w/ values good for the
|
||||||
|
** backend. such as, possible values as just ids, not objects w/ a label;
|
||||||
|
** date-times formatted properly and in UTC
|
||||||
|
*******************************************************************************/
|
||||||
|
public static prepQueryFilterForBackend(tableMetaData: QTableMetaData, sourceFilter: QQueryFilter, pageNumber?: number, rowsPerPage?: number): QQueryFilter
|
||||||
|
{
|
||||||
|
const filterForBackend = new QQueryFilter([], sourceFilter.orderBys, sourceFilter.subFilters, sourceFilter.booleanOperator);
|
||||||
|
for (let i = 0; i < sourceFilter?.criteria?.length; i++)
|
||||||
|
{
|
||||||
|
const criteria = sourceFilter.criteria[i];
|
||||||
|
const {criteriaIsValid} = validateCriteria(criteria, null);
|
||||||
|
if (criteriaIsValid)
|
||||||
|
{
|
||||||
|
if (criteria.operator == QCriteriaOperator.IS_BLANK || criteria.operator == QCriteriaOperator.IS_NOT_BLANK)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// do this to avoid submitting an empty-string argument for blank/not-blank operators... //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
filterForBackend.criteria.push(new QFilterCriteria(criteria.fieldName, criteria.operator, []));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// else push a clone of the criteria - since it may get manipulated below (convertFilterPossibleValuesToIds) //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const [field] = FilterUtils.getField(tableMetaData, criteria.fieldName);
|
||||||
|
filterForBackend.criteria.push(new QFilterCriteria(criteria.fieldName, criteria.operator, FilterUtils.cleanseCriteriaValueForQQQ(criteria.values, field)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// recursively prep subfilters as well //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
let subFilters = [] as QQueryFilter[];
|
||||||
|
for (let j = 0; j < sourceFilter?.subFilters?.length; j++)
|
||||||
|
{
|
||||||
|
subFilters.push(FilterUtils.prepQueryFilterForBackend(tableMetaData, sourceFilter.subFilters[j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
filterForBackend.subFilters = subFilters;
|
||||||
|
|
||||||
|
if(pageNumber !== undefined && rowsPerPage !== undefined)
|
||||||
|
{
|
||||||
|
filterForBackend.skip = pageNumber * rowsPerPage;
|
||||||
|
filterForBackend.limit = rowsPerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterForBackend;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FilterUtils;
|
export default FilterUtils;
|
||||||
|
Reference in New Issue
Block a user