mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-19 22:00:45 +00:00
CE-607 Support fields from an exposed-join on a view screen.
This commit is contained in:
@ -985,6 +985,10 @@ function ProcessRun({process, table, defaultProcessValues, isModal, isWidget, is
|
||||
}
|
||||
setQJobRunning(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.warn(`Process response was not of an expected type (need an npm clean?) ${JSON.stringify(lastProcessResponse)}`);
|
||||
}
|
||||
}
|
||||
}, [lastProcessResponse]);
|
||||
|
||||
|
@ -71,6 +71,7 @@ import DataGridUtils from "qqq/utils/DataGridUtils";
|
||||
import Client from "qqq/utils/qqq/Client";
|
||||
import FilterUtils from "qqq/utils/qqq/FilterUtils";
|
||||
import ProcessUtils from "qqq/utils/qqq/ProcessUtils";
|
||||
import TableUtils from "qqq/utils/qqq/TableUtils";
|
||||
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
||||
|
||||
const CURRENT_SAVED_FILTER_ID_LOCAL_STORAGE_KEY_ROOT = "qqq.currentSavedFilterId";
|
||||
@ -628,6 +629,8 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
let models = await FilterUtils.determineFilterAndSortModels(qController, tableMetaData, null, searchParams, filterLocalStorageKey, sortLocalStorageKey);
|
||||
setFilterModel(models.filter);
|
||||
setColumnSortModel(models.sort);
|
||||
setWarningAlert(models.warning);
|
||||
|
||||
setQueryFilter(FilterUtils.buildQFilterFromGridFilter(tableMetaData, models.filter, models.sort, rowsPerPage));
|
||||
return;
|
||||
}
|
||||
@ -708,16 +711,7 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
if (tableMetaData?.exposedJoins)
|
||||
{
|
||||
const visibleJoinTables = getVisibleJoinTables();
|
||||
|
||||
queryJoins = [];
|
||||
for (let i = 0; i < tableMetaData.exposedJoins.length; i++)
|
||||
{
|
||||
const join = tableMetaData.exposedJoins[i];
|
||||
if (visibleJoinTables.has(join.joinTable.name))
|
||||
{
|
||||
queryJoins.push(new QueryJoin(join.joinTable.name, true, "LEFT"));
|
||||
}
|
||||
}
|
||||
queryJoins = TableUtils.getQueryJoins(tableMetaData, visibleJoinTables);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1400,6 +1394,8 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
const models = await FilterUtils.determineFilterAndSortModels(qController, tableMetaData, qRecord.values.get("filterJson"), null, null, null);
|
||||
handleFilterChange(models.filter);
|
||||
handleSortChange(models.sort, models.filter);
|
||||
setWarningAlert(models.warning);
|
||||
|
||||
localStorage.setItem(currentSavedFilterLocalStorageKey, selectedSavedFilterId.toString());
|
||||
}
|
||||
else
|
||||
@ -1431,35 +1427,13 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
return (qRecord);
|
||||
}
|
||||
|
||||
const getFieldAndTable = (fieldName: string): [QFieldMetaData, QTableMetaData] =>
|
||||
{
|
||||
if(fieldName.indexOf(".") > -1)
|
||||
{
|
||||
const nameParts = fieldName.split(".", 2);
|
||||
for (let i = 0; i < tableMetaData?.exposedJoins?.length; i++)
|
||||
{
|
||||
const join = tableMetaData?.exposedJoins[i];
|
||||
if(join?.joinTable.name == nameParts[0])
|
||||
{
|
||||
return ([join.joinTable.fields.get(nameParts[1]), join.joinTable]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ([tableMetaData.fields.get(fieldName), tableMetaData]);
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
const copyColumnValues = async (column: GridColDef) =>
|
||||
{
|
||||
let data = "";
|
||||
let counter = 0;
|
||||
if (latestQueryResults && latestQueryResults.length)
|
||||
{
|
||||
let [qFieldMetaData, fieldTable] = getFieldAndTable(column.field);
|
||||
let [qFieldMetaData, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, column.field);
|
||||
for (let i = 0; i < latestQueryResults.length; i++)
|
||||
{
|
||||
let record = latestQueryResults[i] as QRecord;
|
||||
@ -1489,7 +1463,7 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
setFilterForColumnStats(buildQFilter(tableMetaData, filterModel));
|
||||
setColumnStatsFieldName(column.field);
|
||||
|
||||
const [field, fieldTable] = getFieldAndTable(column.field);
|
||||
const [field, fieldTable] = TableUtils.getFieldAndTable(tableMetaData, column.field);
|
||||
setColumnStatsField(field);
|
||||
setColumnStatsFieldTableName(fieldTable.name);
|
||||
};
|
||||
@ -1962,7 +1936,7 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
||||
{
|
||||
(warningAlert) ? (
|
||||
<Collapse in={Boolean(warningAlert)}>
|
||||
<Alert color="warning" sx={{mb: 3}} onClose={() => setWarningAlert(null)}>{warningAlert}</Alert>
|
||||
<Alert color="warning" icon={<Icon>warning</Icon>} sx={{mb: 3}} onClose={() => setWarningAlert(null)}>{warningAlert}</Alert>
|
||||
</Collapse>
|
||||
) : null
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QT
|
||||
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
||||
import {QTableVariant} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableVariant";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import {QueryJoin} from "@kingsrook/qqq-frontend-core/lib/model/query/QueryJoin";
|
||||
import {Alert, Typography} from "@mui/material";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
import Box from "@mui/material/Box";
|
||||
@ -103,7 +104,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
||||
const [allTableProcesses, setAllTableProcesses] = useState([] as QProcessMetaData[]);
|
||||
const [actionsMenu, setActionsMenu] = useState(null);
|
||||
const [notFoundMessage, setNotFoundMessage] = useState(null as string);
|
||||
const [errorMessage, setErrorMessage] = useState(null as string)
|
||||
const [errorMessage, setErrorMessage] = useState(null as string);
|
||||
const [successMessage, setSuccessMessage] = useState(null as string);
|
||||
const [warningMessage, setWarningMessage] = useState(null as string);
|
||||
const [activeModalProcess, setActiveModalProcess] = useState(null as QProcessMetaData);
|
||||
@ -325,6 +326,31 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
||||
reload();
|
||||
}, [location.pathname, location.hash]);
|
||||
|
||||
const getVisibleJoinTables = (tableMetaData: QTableMetaData): Set<string> =>
|
||||
{
|
||||
const visibleJoinTables = new Set<string>();
|
||||
|
||||
for (let i = 0; i < tableMetaData?.sections.length; i++)
|
||||
{
|
||||
const section = tableMetaData?.sections[i];
|
||||
if (section.isHidden || !section.fieldNames || !section.fieldNames.length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
section.fieldNames.forEach((fieldName) =>
|
||||
{
|
||||
const [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
||||
if(tableForField && tableForField.name != tableMetaData.name)
|
||||
{
|
||||
visibleJoinTables.add(tableForField.name);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (visibleJoinTables);
|
||||
};
|
||||
|
||||
if (!asyncLoadInited)
|
||||
{
|
||||
setAsyncLoadInited(true);
|
||||
@ -368,13 +394,20 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
||||
setActiveModalProcess(launchingProcess);
|
||||
}
|
||||
|
||||
let queryJoins: QueryJoin[] = null;
|
||||
const visibleJoinTables = getVisibleJoinTables(tableMetaData);
|
||||
if(visibleJoinTables.size > 0)
|
||||
{
|
||||
queryJoins = TableUtils.getQueryJoins(tableMetaData, visibleJoinTables);
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// load the record //
|
||||
/////////////////////
|
||||
let record: QRecord;
|
||||
try
|
||||
{
|
||||
record = await qController.get(tableName, id, tableVariant);
|
||||
record = await qController.get(tableName, id, tableVariant, null, queryJoins);
|
||||
setRecord(record);
|
||||
}
|
||||
catch (e)
|
||||
@ -465,17 +498,22 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
||||
const fields = (
|
||||
<Box key={section.name} display="flex" flexDirection="column" py={1} pr={2}>
|
||||
{
|
||||
section.fieldNames.map((fieldName: string) => (
|
||||
<Box key={fieldName} flexDirection="row" pr={2}>
|
||||
<Typography variant="button" textTransform="none" fontWeight="bold" pr={1} color="rgb(52, 71, 103)">
|
||||
{tableMetaData.fields.get(fieldName).label}:
|
||||
<div style={{display: "inline-block", width: 0}}> </div>
|
||||
</Typography>
|
||||
<Typography variant="button" textTransform="none" fontWeight="regular" color="rgb(123, 128, 154)">
|
||||
{ValueUtils.getDisplayValue(tableMetaData.fields.get(fieldName), record, "view")}
|
||||
</Typography>
|
||||
</Box>
|
||||
))
|
||||
section.fieldNames.map((fieldName: string) =>
|
||||
{
|
||||
let [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
||||
let label = field.label;
|
||||
return (
|
||||
<Box key={fieldName} flexDirection="row" pr={2}>
|
||||
<Typography variant="button" textTransform="none" fontWeight="bold" pr={1} color="rgb(52, 71, 103)">
|
||||
{label}:
|
||||
<div style={{display: "inline-block", width: 0}}> </div>
|
||||
</Typography>
|
||||
<Typography variant="button" textTransform="none" fontWeight="regular" color="rgb(123, 128, 154)">
|
||||
{ValueUtils.getDisplayValue(field, record, "view", fieldName)}
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Box>
|
||||
);
|
||||
|
Reference in New Issue
Block a user