CE-1115 Add sort indication to report setup; make recordQuery, when being used for report setup, not write local storage;

This commit is contained in:
2024-04-16 20:39:33 -05:00
parent 73c907a3e1
commit cb3162f084
3 changed files with 65 additions and 18 deletions

View File

@ -85,6 +85,26 @@ interface BasicAndAdvancedQueryControlsProps
let debounceTimeout: string | number | NodeJS.Timeout; let debounceTimeout: string | number | NodeJS.Timeout;
/*******************************************************************************
** function to generate an element that says how a filter is sorted.
*******************************************************************************/
export function getCurrentSortIndicator(queryFilter: QQueryFilter, tableMetaData: QTableMetaData, toggleSortDirection: (event: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void)
{
if (queryFilter && queryFilter.orderBys && queryFilter.orderBys.length > 0)
{
const orderBy = queryFilter.orderBys[0];
const orderByFieldName = orderBy.fieldName;
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, orderByFieldName);
const fieldLabel = fieldTable.name == tableMetaData.name ? field.label : `${fieldTable.label}: ${field.label}`;
return <>Sort: {fieldLabel} <Icon onClick={toggleSortDirection} sx={{ml: "0.5rem"}}>{orderBy.isAscending ? "arrow_upward" : "arrow_downward"}</Icon></>;
}
else
{
return <>Sort...</>;
}
}
/******************************************************************************* /*******************************************************************************
** Component to provide the basic & advanced query-filter controls for the ** Component to provide the basic & advanced query-filter controls for the
** RecordQueryOrig screen. ** RecordQueryOrig screen.
@ -558,15 +578,7 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
///////////////////////////////// /////////////////////////////////
// set up the sort menu button // // set up the sort menu button //
///////////////////////////////// /////////////////////////////////
let sortButtonContents = <>Sort...</>; let sortButtonContents = getCurrentSortIndicator(queryFilter, tableMetaData, toggleSortDirection);
if (queryFilter && queryFilter.orderBys && queryFilter.orderBys.length > 0)
{
const orderBy = queryFilter.orderBys[0];
const orderByFieldName = orderBy.fieldName;
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, orderByFieldName);
const fieldLabel = fieldTable.name == tableMetaData.name ? field.label : `${fieldTable.label}: ${field.label}`;
sortButtonContents = <>Sort: {fieldLabel} <Icon onClick={toggleSortDirection} sx={{ml: "0.5rem"}}>{orderBy.isAscending ? "arrow_upward" : "arrow_downward"}</Icon></>;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
// this is being used as a version of like forcing that we get re-rendered if the query filter changes... // // this is being used as a version of like forcing that we get re-rendered if the query filter changes... //

View File

@ -34,6 +34,7 @@ import colors from "qqq/assets/theme/base/colors";
import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons"; import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent"; import HelpContent, {hasHelpContent} from "qqq/components/misc/HelpContent";
import AdvancedQueryPreview from "qqq/components/query/AdvancedQueryPreview"; import AdvancedQueryPreview from "qqq/components/query/AdvancedQueryPreview";
import {getCurrentSortIndicator} from "qqq/components/query/BasicAndAdvancedQueryControls";
import Widget, {HeaderLinkButtonComponent} from "qqq/components/widgets/Widget"; import Widget, {HeaderLinkButtonComponent} from "qqq/components/widgets/Widget";
import QQueryColumns, {Column} from "qqq/models/query/QQueryColumns"; import QQueryColumns, {Column} from "qqq/models/query/QQueryColumns";
import RecordQuery from "qqq/pages/records/query/RecordQuery"; import RecordQuery from "qqq/pages/records/query/RecordQuery";
@ -101,9 +102,11 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
// load values from record // // load values from record //
///////////////////////////// /////////////////////////////
let queryFilter = recordValues["queryFilterJson"] && JSON.parse(recordValues["queryFilterJson"]) as QQueryFilter; let queryFilter = recordValues["queryFilterJson"] && JSON.parse(recordValues["queryFilterJson"]) as QQueryFilter;
let usingDefaultEmptyFilter = false;
if(!queryFilter) if(!queryFilter)
{ {
queryFilter = new QQueryFilter(); queryFilter = new QQueryFilter();
usingDefaultEmptyFilter = true;
} }
let columns: QQueryColumns = null; let columns: QQueryColumns = null;
@ -285,7 +288,10 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
<Alert severity="error" sx={{mt: 1.5, mb: 0.5}} onClose={() => setAlertContent(null)}>{alertContent}</Alert> <Alert severity="error" sx={{mt: 1.5, mb: 0.5}} onClose={() => setAlertContent(null)}>{alertContent}</Alert>
</Collapse> </Collapse>
<Box pt="0.5rem"> <Box pt="0.5rem">
<h5>Query Filter</h5> <Box display="flex" justifyContent="space-between" alignItems="center">
<h5>Query Filter</h5>
<Box fontSize="0.75rem" fontWeight="700">{mayShowQueryPreview() && getCurrentSortIndicator(frontendQueryFilter, tableMetaData, null)}</Box>
</Box>
{ {
mayShowQueryPreview() && mayShowQueryPreview() &&
<AdvancedQueryPreview tableMetaData={tableMetaData} queryFilter={frontendQueryFilter} isEditable={false} isQueryTooComplex={frontendQueryFilter.subFilters?.length > 0} removeCriteriaByIndexCallback={null} /> <AdvancedQueryPreview tableMetaData={tableMetaData} queryFilter={frontendQueryFilter} isEditable={false} isQueryTooComplex={frontendQueryFilter.subFilters?.length > 0} removeCriteriaByIndexCallback={null} />
@ -347,7 +353,7 @@ export default function ReportSetupWidget({isEditable, widgetMetaData, recordVal
table={tableMetaData} table={tableMetaData}
usage="reportSetup" usage="reportSetup"
isModal={true} isModal={true}
initialQueryFilter={frontendQueryFilter} initialQueryFilter={usingDefaultEmptyFilter ? null : frontendQueryFilter}
initialColumns={columns} initialColumns={columns}
/> />
} }

View File

@ -141,6 +141,34 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
const [firstRender, setFirstRender] = useState(true); const [firstRender, setFirstRender] = useState(true);
const [isFirstRenderAfterChangingTables, setIsFirstRenderAfterChangingTables] = useState(false); const [isFirstRenderAfterChangingTables, setIsFirstRenderAfterChangingTables] = useState(false);
const [loadedFilterFromInitialFilterParam, setLoadedFilterFromInitialFilterParam] = useState(false);
const mayWriteLocalStorage = usage == "queryScreen";
/*******************************************************************************
**
*******************************************************************************/
function localStorageSet(key: string, value: string)
{
if(mayWriteLocalStorage)
{
localStorage.setItem(key, value);
}
}
/*******************************************************************************
**
*******************************************************************************/
function localStorageRemove(key: string)
{
if(mayWriteLocalStorage)
{
localStorage.removeItem(key);
}
}
useImperativeHandle(ref, () => useImperativeHandle(ref, () =>
{ {
return { return {
@ -232,13 +260,14 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
{ {
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// allow a caller to send in an initial filter & set of columns. // // allow a caller to send in an initial filter & set of columns. //
// only to be used on "first render" // // only to be used on "first render". //
// JSON.parse(JSON.stringify()) to do deep clone and keep object clean // // JSON.parse(JSON.stringify()) to do deep clone and keep object clean //
// unclear why not needed on initialColumns... // // unclear why not needed on initialColumns... //
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
if (initialQueryFilter) if (initialQueryFilter)
{ {
defaultView.queryFilter = JSON.parse(JSON.stringify(initialQueryFilter)); defaultView.queryFilter = JSON.parse(JSON.stringify(initialQueryFilter));
setLoadedFilterFromInitialFilterParam(true);
} }
if (initialColumns) if (initialColumns)
@ -720,7 +749,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
{ {
FilterUtils.stripAwayIncompleteCriteria(viewForLocalStorage.queryFilter) FilterUtils.stripAwayIncompleteCriteria(viewForLocalStorage.queryFilter)
} }
localStorage.setItem(viewLocalStorageKey, JSON.stringify(viewForLocalStorage)); localStorageSet(viewLocalStorageKey, JSON.stringify(viewForLocalStorage));
} }
catch(e) catch(e)
{ {
@ -1108,7 +1137,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
if (state && state.density && state.density.value !== density) if (state && state.density && state.density.value !== density)
{ {
setDensity(state.density.value); setDensity(state.density.value);
localStorage.setItem(densityLocalStorageKey, JSON.stringify(state.density.value)); localStorageSet(densityLocalStorageKey, JSON.stringify(state.density.value));
} }
}; };
@ -1605,7 +1634,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// todo can/should/does this move into the view's "identity"? // // todo can/should/does this move into the view's "identity"? //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
localStorage.setItem(currentSavedViewLocalStorageKey, `${savedViewRecord.values.get("id")}`); localStorageSet(currentSavedViewLocalStorageKey, `${savedViewRecord.values.get("id")}`);
}; };
@ -1615,7 +1644,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
const doClearCurrentSavedView = () => const doClearCurrentSavedView = () =>
{ {
setCurrentSavedView(null); setCurrentSavedView(null);
localStorage.removeItem(currentSavedViewLocalStorageKey); localStorageRemove(currentSavedViewLocalStorageKey);
}; };
@ -1662,7 +1691,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
// wipe away the saved view // // wipe away the saved view //
////////////////////////////// //////////////////////////////
setCurrentSavedView(null); setCurrentSavedView(null);
localStorage.removeItem(currentSavedViewLocalStorageKey); localStorageRemove(currentSavedViewLocalStorageKey);
/////////////////////////////////////////////// ///////////////////////////////////////////////
// activate a new default view for the table // // activate a new default view for the table //
@ -2484,7 +2513,7 @@ const RecordQuery = forwardRef(({table, usage, isModal, initialQueryFilter, init
// if the last time we were on this table, a currentSavedView was written to local storage - // // if the last time we were on this table, a currentSavedView was written to local storage - //
// then navigate back to that view's URL - unless - it looks like we're on a process! // // then navigate back to that view's URL - unless - it looks like we're on a process! //
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
if (localStorage.getItem(currentSavedViewLocalStorageKey) && !urlLooksLikeProcess()) if (localStorage.getItem(currentSavedViewLocalStorageKey) && !urlLooksLikeProcess() && !loadedFilterFromInitialFilterParam)
{ {
const currentSavedViewId = Number.parseInt(localStorage.getItem(currentSavedViewLocalStorageKey)); const currentSavedViewId = Number.parseInt(localStorage.getItem(currentSavedViewLocalStorageKey));
console.log(`returning to previously active saved view ${currentSavedViewId}`); console.log(`returning to previously active saved view ${currentSavedViewId}`);