mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
CE-936 - Add support for managing associations on insert/edit screens, via childRecordList widget
This commit is contained in:
@ -137,7 +137,7 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
*******************************************************************************/
|
||||
public Builder withCanAddChildRecord(boolean b)
|
||||
{
|
||||
widgetMetaData.withDefaultValue("canAddChildRecord", true);
|
||||
widgetMetaData.withDefaultValue("canAddChildRecord", b);
|
||||
return (this);
|
||||
}
|
||||
|
||||
@ -151,6 +151,17 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
widgetMetaData.withDefaultValue("disabledFieldsForNewChildRecords", new HashSet<>(disabledFieldsForNewChildRecords));
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Builder withManageAssociationName(String manageAssociationName)
|
||||
{
|
||||
widgetMetaData.withDefaultValue("manageAssociationName", manageAssociationName);
|
||||
return (this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -178,52 +189,60 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
maxRows = ValueUtils.getValueAsInteger(input.getWidgetMetaData().getDefaultValues().containsKey("maxRows"));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// fetch the record that we're getting children for. //
|
||||
// e.g., the left-side of the join, with the input id //
|
||||
////////////////////////////////////////////////////////
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(join.getLeftTable());
|
||||
getInput.setPrimaryKey(id);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
QRecord record = getOutput.getRecord();
|
||||
|
||||
if(record == null)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// fetch the record that we're getting children for. e.g., the left-side of the join, with the input id //
|
||||
// but - only try this if we were given an id. note, this widget could be called for on an INSERT screen, where we don't have a record yet //
|
||||
// but we still want to be able to return all the other data in here that otherwise comes from the widget meta data, join, etc. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int totalRows = 0;
|
||||
QRecord primaryRecord = null;
|
||||
QQueryFilter filter = null;
|
||||
QueryOutput queryOutput = new QueryOutput(new QueryInput());
|
||||
if(StringUtils.hasContent(id))
|
||||
{
|
||||
throw (new QNotFoundException("Could not find " + (leftTable == null ? "" : leftTable.getLabel()) + " with primary key " + id));
|
||||
}
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(join.getLeftTable());
|
||||
getInput.setPrimaryKey(id);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
primaryRecord = getOutput.getRecord();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// set up the query - for the table on the right side of the join //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
QQueryFilter filter = new QQueryFilter();
|
||||
for(JoinOn joinOn : join.getJoinOns())
|
||||
{
|
||||
filter.addCriteria(new QFilterCriteria(joinOn.getRightField(), QCriteriaOperator.EQUALS, List.of(record.getValue(joinOn.getLeftField()))));
|
||||
}
|
||||
filter.setOrderBys(join.getOrderBys());
|
||||
filter.setLimit(maxRows);
|
||||
if(primaryRecord == null)
|
||||
{
|
||||
throw (new QNotFoundException("Could not find " + (leftTable == null ? "" : leftTable.getLabel()) + " with primary key " + id));
|
||||
}
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(join.getRightTable());
|
||||
queryInput.setShouldTranslatePossibleValues(true);
|
||||
queryInput.setShouldGenerateDisplayValues(true);
|
||||
queryInput.setFilter(filter);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// set up the query - for the table on the right side of the join //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
filter = new QQueryFilter();
|
||||
for(JoinOn joinOn : join.getJoinOns())
|
||||
{
|
||||
filter.addCriteria(new QFilterCriteria(joinOn.getRightField(), QCriteriaOperator.EQUALS, List.of(primaryRecord.getValue(joinOn.getLeftField()))));
|
||||
}
|
||||
filter.setOrderBys(join.getOrderBys());
|
||||
filter.setLimit(maxRows);
|
||||
|
||||
QValueFormatter.setBlobValuesToDownloadUrls(rightTable, queryOutput.getRecords());
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(join.getRightTable());
|
||||
queryInput.setShouldTranslatePossibleValues(true);
|
||||
queryInput.setShouldGenerateDisplayValues(true);
|
||||
queryInput.setFilter(filter);
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
|
||||
int totalRows = queryOutput.getRecords().size();
|
||||
if(maxRows != null && (queryOutput.getRecords().size() == maxRows))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the input said to only do some max, and the # of results we got is that max, //
|
||||
// then do a count query, for displaying 1-n of <count> //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(join.getRightTable());
|
||||
countInput.setFilter(filter);
|
||||
totalRows = new CountAction().execute(countInput).getCount();
|
||||
QValueFormatter.setBlobValuesToDownloadUrls(rightTable, queryOutput.getRecords());
|
||||
|
||||
totalRows = queryOutput.getRecords().size();
|
||||
if(maxRows != null && (queryOutput.getRecords().size() == maxRows))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the input said to only do some max, and the # of results we got is that max, //
|
||||
// then do a count query, for displaying 1-n of <count> //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(join.getRightTable());
|
||||
countInput.setFilter(filter);
|
||||
totalRows = new CountAction().execute(countInput).getCount();
|
||||
}
|
||||
}
|
||||
|
||||
String tablePath = input.getInstance().getTablePath(rightTable.getName());
|
||||
@ -239,10 +258,14 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
// new child records must have values from the join-ons //
|
||||
//////////////////////////////////////////////////////////
|
||||
Map<String, Serializable> defaultValuesForNewChildRecords = new HashMap<>();
|
||||
for(JoinOn joinOn : join.getJoinOns())
|
||||
if(primaryRecord != null)
|
||||
{
|
||||
defaultValuesForNewChildRecords.put(joinOn.getRightField(), record.getValue(joinOn.getLeftField()));
|
||||
for(JoinOn joinOn : join.getJoinOns())
|
||||
{
|
||||
defaultValuesForNewChildRecords.put(joinOn.getRightField(), primaryRecord.getValue(joinOn.getLeftField()));
|
||||
}
|
||||
}
|
||||
|
||||
widgetData.setDefaultValuesForNewChildRecords(defaultValuesForNewChildRecords);
|
||||
|
||||
Map<String, Serializable> widgetValues = input.getWidgetMetaData().getDefaultValues();
|
||||
@ -250,6 +273,22 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
{
|
||||
widgetData.setDisabledFieldsForNewChildRecords((Set<String>) widgetValues.get("disabledFieldsForNewChildRecords"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if there are no disabled fields specified - then normally any fields w/ a default value get implicitly disabled //
|
||||
// but - if we didn't look-up the primary record, then we'll want to explicit disable fields from joins //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(primaryRecord == null)
|
||||
{
|
||||
Set<String> implicitlyDisabledFields = new HashSet<>();
|
||||
widgetData.setDisabledFieldsForNewChildRecords(implicitlyDisabledFields);
|
||||
for(JoinOn joinOn : join.getJoinOns())
|
||||
{
|
||||
implicitlyDisabledFields.add(joinOn.getRightField());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (new RenderWidgetOutput(widgetData));
|
||||
|
@ -22,6 +22,7 @@
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
@ -60,6 +61,7 @@ public class QFrontendWidgetMetaData
|
||||
|
||||
protected Map<String, QIcon> icons;
|
||||
protected Map<String, QHelpContent> helpContent;
|
||||
protected Map<String, Serializable> defaultValues;
|
||||
|
||||
private final boolean hasPermission;
|
||||
|
||||
@ -95,6 +97,7 @@ public class QFrontendWidgetMetaData
|
||||
}
|
||||
|
||||
this.helpContent = widgetMetaData.getHelpContent();
|
||||
this.defaultValues = widgetMetaData.getDefaultValues();
|
||||
|
||||
hasPermission = PermissionsHelper.hasWidgetPermission(actionInput, name);
|
||||
}
|
||||
@ -274,4 +277,16 @@ public class QFrontendWidgetMetaData
|
||||
{
|
||||
return helpContent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for defaultValues
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Map<String, Serializable> getDefaultValues()
|
||||
{
|
||||
return defaultValues;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -779,9 +779,30 @@ public class QJavalinImplementation
|
||||
{
|
||||
String fieldName = formParam.getKey();
|
||||
List<String> values = formParam.getValue();
|
||||
String value = values.get(0);
|
||||
|
||||
if("associations".equals(fieldName) && StringUtils.hasContent(value))
|
||||
{
|
||||
JSONObject associationsJSON = new JSONObject(value);
|
||||
for(String key : associationsJSON.keySet())
|
||||
{
|
||||
JSONArray associatedRecords = associationsJSON.getJSONArray(key);
|
||||
for(int i = 0; i < associatedRecords.length(); i++)
|
||||
{
|
||||
QRecord associatedRecord = new QRecord();
|
||||
JSONObject recordJSON = associatedRecords.getJSONObject(i);
|
||||
for(String k : recordJSON.keySet())
|
||||
{
|
||||
associatedRecord.withValue(k, ValueUtils.getValueAsString(recordJSON.get(k)));
|
||||
}
|
||||
record.withAssociatedRecord(key, associatedRecord);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(values))
|
||||
{
|
||||
String value = values.get(0);
|
||||
if(StringUtils.hasContent(value))
|
||||
{
|
||||
record.setValue(fieldName, value);
|
||||
|
Reference in New Issue
Block a user