mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 12:50:43 +00:00
Add support for defaultValuesForNewChildRecordsFromParentFields for ChildRecordList; Load display values for possible-value fields when adding them to childRecord list and when opening child-edit form (adding passing of all other-values to the possible-value lookup, for filtered scenarios that need them);
This commit is contained in:
@ -66,7 +66,7 @@ interface Props
|
|||||||
defaultValues: { [key: string]: string };
|
defaultValues: { [key: string]: string };
|
||||||
disabledFields: { [key: string]: boolean } | string[];
|
disabledFields: { [key: string]: boolean } | string[];
|
||||||
isCopy?: boolean;
|
isCopy?: boolean;
|
||||||
onSubmitCallback?: (values: any) => void;
|
onSubmitCallback?: (values: any, tableName: string) => void;
|
||||||
overrideHeading?: string;
|
overrideHeading?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
function openAddChildRecord(name: string, widgetData: any)
|
function openAddChildRecord(name: string, widgetData: any)
|
||||||
{
|
{
|
||||||
let defaultValues = widgetData.defaultValuesForNewChildRecords;
|
let defaultValues = widgetData.defaultValuesForNewChildRecords || {};
|
||||||
|
|
||||||
let disabledFields = widgetData.disabledFieldsForNewChildRecords;
|
let disabledFields = widgetData.disabledFieldsForNewChildRecords;
|
||||||
if (!disabledFields)
|
if (!disabledFields)
|
||||||
@ -181,6 +181,18 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
disabledFields = widgetData.defaultValuesForNewChildRecords;
|
disabledFields = widgetData.defaultValuesForNewChildRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// copy values from specified fields in the parent record down into the child record //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(widgetData.defaultValuesForNewChildRecordsFromParentFields)
|
||||||
|
{
|
||||||
|
for(let childField in widgetData.defaultValuesForNewChildRecordsFromParentFields)
|
||||||
|
{
|
||||||
|
const parentField = widgetData.defaultValuesForNewChildRecordsFromParentFields[childField];
|
||||||
|
defaultValues[childField] = formValues[parentField];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
doOpenEditChildForm(name, widgetData.childTableMetaData, null, defaultValues, disabledFields);
|
doOpenEditChildForm(name, widgetData.childTableMetaData, null, defaultValues, disabledFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +220,7 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
function deleteChildRecord(name: string, widgetData: any, rowIndex: number)
|
function deleteChildRecord(name: string, widgetData: any, rowIndex: number)
|
||||||
{
|
{
|
||||||
updateChildRecordList(name, "delete", rowIndex);
|
updateChildRecordList(name, "delete", rowIndex);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -243,16 +255,16 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
function submitEditChildForm(values: any)
|
function submitEditChildForm(values: any, tableName: string)
|
||||||
{
|
{
|
||||||
updateChildRecordList(showEditChildForm.widgetName, showEditChildForm.rowIndex == null ? "insert" : "edit", showEditChildForm.rowIndex, values);
|
updateChildRecordList(showEditChildForm.widgetName, showEditChildForm.rowIndex == null ? "insert" : "edit", showEditChildForm.rowIndex, values, tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
async function updateChildRecordList(widgetName: string, action: "insert" | "edit" | "delete", rowIndex?: number, values?: any)
|
async function updateChildRecordList(widgetName: string, action: "insert" | "edit" | "delete", rowIndex?: number, values?: any, childTableName?: string)
|
||||||
{
|
{
|
||||||
const metaData = await qController.loadMetaData();
|
const metaData = await qController.loadMetaData();
|
||||||
const widgetMetaData = metaData.widgets.get(widgetName);
|
const widgetMetaData = metaData.widgets.get(widgetName);
|
||||||
@ -263,13 +275,38 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
newChildListWidgetData[widgetName].queryOutput.records = [];
|
newChildListWidgetData[widgetName].queryOutput.records = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// build a map of display values for the new record, specifically, for any possible-values that need translated. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const displayValues: {[fieldName: string]: string} = {};
|
||||||
|
if(childTableName && values)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// this function internally memoizes, so, we could potentially avoid an await here, but, seems ok... //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const childTableMetaData = await qController.loadTableMetaData(childTableName)
|
||||||
|
for (let key in values)
|
||||||
|
{
|
||||||
|
const value = values[key];
|
||||||
|
const field = childTableMetaData.fields.get(key);
|
||||||
|
if(field.possibleValueSourceName)
|
||||||
|
{
|
||||||
|
const possibleValues = await qController.possibleValues(childTableName, null, field.name, null, [value], objectToMap(values), "form")
|
||||||
|
if(possibleValues && possibleValues.length > 0)
|
||||||
|
{
|
||||||
|
displayValues[key] = possibleValues[0].label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case "insert":
|
case "insert":
|
||||||
newChildListWidgetData[widgetName].queryOutput.records.push({values: values});
|
newChildListWidgetData[widgetName].queryOutput.records.push({values: values, displayValues: displayValues});
|
||||||
break;
|
break;
|
||||||
case "edit":
|
case "edit":
|
||||||
newChildListWidgetData[widgetName].queryOutput.records[rowIndex] = {values: values};
|
newChildListWidgetData[widgetName].queryOutput.records[rowIndex] = {values: values, displayValues: displayValues};
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
newChildListWidgetData[widgetName].queryOutput.records.splice(rowIndex, 1);
|
newChildListWidgetData[widgetName].queryOutput.records.splice(rowIndex, 1);
|
||||||
@ -479,6 +516,26 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
function objectToMap(object: { [key: string]: any }): Map<string, any>
|
||||||
|
{
|
||||||
|
if(object == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rs = new Map<string, any>();
|
||||||
|
for (let key in object)
|
||||||
|
{
|
||||||
|
rs.set(key, object[key]);
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// initial load //
|
// initial load //
|
||||||
//////////////////
|
//////////////////
|
||||||
@ -596,18 +653,24 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
if (defaultValue)
|
if (defaultValue)
|
||||||
{
|
{
|
||||||
initialValues[fieldName] = defaultValue;
|
initialValues[fieldName] = defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we need to set the initialDisplayValue for possible value fields with a default value //
|
// do a second loop, this time looking up display-values for any possible-value fields with a default value //
|
||||||
// so, look them up here now if needed //
|
// do it in a second loop, to pass in all the other values (from initialValues), in case there's a PVS filter that needs them. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if (fieldMetaData.possibleValueSourceName)
|
for (let i = 0; i < fieldArray.length; i++)
|
||||||
|
{
|
||||||
|
const fieldMetaData = fieldArray[i];
|
||||||
|
const fieldName = fieldMetaData.name;
|
||||||
|
const defaultValue = (defaultValues && defaultValues[fieldName]) ? defaultValues[fieldName] : fieldMetaData.defaultValue;
|
||||||
|
if (defaultValue && fieldMetaData.possibleValueSourceName)
|
||||||
|
{
|
||||||
|
const results: QPossibleValue[] = await qController.possibleValues(tableName, null, fieldName, null, [initialValues[fieldName]], objectToMap(initialValues), "form");
|
||||||
|
if (results && results.length > 0)
|
||||||
{
|
{
|
||||||
const results: QPossibleValue[] = await qController.possibleValues(tableName, null, fieldName, null, [initialValues[fieldName]], undefined, "form");
|
defaultDisplayValues.set(fieldName, results[0].label);
|
||||||
if (results && results.length > 0)
|
|
||||||
{
|
|
||||||
defaultDisplayValues.set(fieldName, results[0].label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -824,7 +887,7 @@ function EntityForm(props: Props): JSX.Element
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if (props.onSubmitCallback)
|
if (props.onSubmitCallback)
|
||||||
{
|
{
|
||||||
props.onSubmitCallback(values);
|
props.onSubmitCallback(values, tableName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
function submitEditChildForm(values: any)
|
function submitEditChildForm(values: any, tableName: string)
|
||||||
{
|
{
|
||||||
updateChildRecordList(showEditChildForm.widgetName, showEditChildForm.rowIndex == null ? "insert" : "edit", showEditChildForm.rowIndex, values);
|
updateChildRecordList(showEditChildForm.widgetName, showEditChildForm.rowIndex == null ? "insert" : "edit", showEditChildForm.rowIndex, values);
|
||||||
let widgetIndex = determineChildRecordListIndex(showEditChildForm.widgetName);
|
let widgetIndex = determineChildRecordListIndex(showEditChildForm.widgetName);
|
||||||
@ -718,6 +718,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, reco
|
|||||||
addNewRecordCallback={widgetData[i]?.isInProcess ? () => openAddChildRecord(widgetMetaData.name, widgetData[i]) : null}
|
addNewRecordCallback={widgetData[i]?.isInProcess ? () => openAddChildRecord(widgetMetaData.name, widgetData[i]) : null}
|
||||||
widgetMetaData={widgetMetaData}
|
widgetMetaData={widgetMetaData}
|
||||||
data={widgetData[i]}
|
data={widgetData[i]}
|
||||||
|
parentRecord={record}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ import {Link, useNavigate} from "react-router-dom";
|
|||||||
export interface ChildRecordListData extends WidgetData
|
export interface ChildRecordListData extends WidgetData
|
||||||
{
|
{
|
||||||
title?: string;
|
title?: string;
|
||||||
queryOutput?: { records: { values: any }[] };
|
queryOutput?: { records: { values: any, displayValues?: any } [] };
|
||||||
childTableMetaData?: QTableMetaData;
|
childTableMetaData?: QTableMetaData;
|
||||||
tablePath?: string;
|
tablePath?: string;
|
||||||
viewAllLink?: string;
|
viewAllLink?: string;
|
||||||
@ -48,20 +48,22 @@ export interface ChildRecordListData extends WidgetData
|
|||||||
canAddChildRecord?: boolean;
|
canAddChildRecord?: boolean;
|
||||||
defaultValuesForNewChildRecords?: { [fieldName: string]: any };
|
defaultValuesForNewChildRecords?: { [fieldName: string]: any };
|
||||||
disabledFieldsForNewChildRecords?: { [fieldName: string]: any };
|
disabledFieldsForNewChildRecords?: { [fieldName: string]: any };
|
||||||
|
defaultValuesForNewChildRecordsFromParentFields?: { [fieldName: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
widgetMetaData: QWidgetMetaData;
|
widgetMetaData: QWidgetMetaData,
|
||||||
data: ChildRecordListData;
|
data: ChildRecordListData,
|
||||||
addNewRecordCallback?: () => void;
|
addNewRecordCallback?: () => void,
|
||||||
disableRowClick: boolean;
|
disableRowClick: boolean,
|
||||||
allowRecordEdit: boolean;
|
allowRecordEdit: boolean,
|
||||||
editRecordCallback?: (rowIndex: number) => void;
|
editRecordCallback?: (rowIndex: number) => void,
|
||||||
allowRecordDelete: boolean;
|
allowRecordDelete: boolean,
|
||||||
deleteRecordCallback?: (rowIndex: number) => void;
|
deleteRecordCallback?: (rowIndex: number) => void,
|
||||||
gridOnly?: boolean;
|
gridOnly?: boolean,
|
||||||
gridDensity?: GridDensity;
|
gridDensity?: GridDensity,
|
||||||
|
parentRecord?: QRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordGridWidget.defaultProps =
|
RecordGridWidget.defaultProps =
|
||||||
@ -74,7 +76,7 @@ RecordGridWidget.defaultProps =
|
|||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
|
|
||||||
function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRowClick, allowRecordEdit, editRecordCallback, allowRecordDelete, deleteRecordCallback, gridOnly, gridDensity}: Props): JSX.Element
|
function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRowClick, allowRecordEdit, editRecordCallback, allowRecordDelete, deleteRecordCallback, gridOnly, gridDensity, parentRecord}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const instance = useRef({timer: null});
|
const instance = useRef({timer: null});
|
||||||
const [rows, setRows] = useState([]);
|
const [rows, setRows] = useState([]);
|
||||||
@ -97,7 +99,7 @@ function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRo
|
|||||||
{
|
{
|
||||||
for (let i = 0; i < queryOutputRecords.length; i++)
|
for (let i = 0; i < queryOutputRecords.length; i++)
|
||||||
{
|
{
|
||||||
if(queryOutputRecords[i] instanceof QRecord)
|
if (queryOutputRecords[i] instanceof QRecord)
|
||||||
{
|
{
|
||||||
records.push(queryOutputRecords[i] as QRecord);
|
records.push(queryOutputRecords[i] as QRecord);
|
||||||
}
|
}
|
||||||
@ -252,7 +254,22 @@ function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRo
|
|||||||
{
|
{
|
||||||
disabledFields = data.defaultValuesForNewChildRecords;
|
disabledFields = data.defaultValuesForNewChildRecords;
|
||||||
}
|
}
|
||||||
labelAdditionalComponentsRight.push(new AddNewRecordButton(data.childTableMetaData, data.defaultValuesForNewChildRecords, "Add new", disabledFields, addNewRecordCallback));
|
|
||||||
|
const defaultValuesForNewChildRecords = data.defaultValuesForNewChildRecords || {}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// copy values from specified fields in the parent record down into the child record //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(data.defaultValuesForNewChildRecordsFromParentFields)
|
||||||
|
{
|
||||||
|
for(let childField in data.defaultValuesForNewChildRecordsFromParentFields)
|
||||||
|
{
|
||||||
|
const parentField = data.defaultValuesForNewChildRecordsFromParentFields[childField];
|
||||||
|
defaultValuesForNewChildRecords[childField] = parentRecord?.values?.get(parentField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labelAdditionalComponentsRight.push(new AddNewRecordButton(data.childTableMetaData, defaultValuesForNewChildRecords, "Add new", disabledFields, addNewRecordCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -357,7 +374,7 @@ function RecordGridWidget({widgetMetaData, data, addNewRecordCallback, disableRo
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
if(gridOnly)
|
if (gridOnly)
|
||||||
{
|
{
|
||||||
return (grid);
|
return (grid);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export interface ModalEditFormData
|
|||||||
defaultValues?: { [key: string]: string };
|
defaultValues?: { [key: string]: string };
|
||||||
disabledFields?: { [key: string]: boolean } | string[];
|
disabledFields?: { [key: string]: boolean } | string[];
|
||||||
overrideHeading?: string;
|
overrideHeading?: string;
|
||||||
onSubmitCallback?: (values: any) => void;
|
onSubmitCallback?: (values: any, tableName: String) => void;
|
||||||
initialShowModalValue?: boolean;
|
initialShowModalValue?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user