mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +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)
|
public Builder withCanAddChildRecord(boolean b)
|
||||||
{
|
{
|
||||||
widgetMetaData.withDefaultValue("canAddChildRecord", true);
|
widgetMetaData.withDefaultValue("canAddChildRecord", b);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +151,17 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
|||||||
widgetMetaData.withDefaultValue("disabledFieldsForNewChildRecords", new HashSet<>(disabledFieldsForNewChildRecords));
|
widgetMetaData.withDefaultValue("disabledFieldsForNewChildRecords", new HashSet<>(disabledFieldsForNewChildRecords));
|
||||||
return (this);
|
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"));
|
maxRows = ValueUtils.getValueAsInteger(input.getWidgetMetaData().getDefaultValues().containsKey("maxRows"));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// fetch the record that we're getting children for. //
|
// fetch the record that we're getting children for. e.g., the left-side of the join, with the input id //
|
||||||
// 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. //
|
||||||
GetInput getInput = new GetInput();
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
getInput.setTableName(join.getLeftTable());
|
int totalRows = 0;
|
||||||
getInput.setPrimaryKey(id);
|
QRecord primaryRecord = null;
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
QQueryFilter filter = null;
|
||||||
QRecord record = getOutput.getRecord();
|
QueryOutput queryOutput = new QueryOutput(new QueryInput());
|
||||||
|
if(StringUtils.hasContent(id))
|
||||||
if(record == null)
|
|
||||||
{
|
{
|
||||||
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();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
if(primaryRecord == null)
|
||||||
// set up the query - for the table on the right side of the join //
|
{
|
||||||
////////////////////////////////////////////////////////////////////
|
throw (new QNotFoundException("Could not find " + (leftTable == null ? "" : leftTable.getLabel()) + " with primary key " + id));
|
||||||
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);
|
|
||||||
|
|
||||||
QueryInput queryInput = new QueryInput();
|
////////////////////////////////////////////////////////////////////
|
||||||
queryInput.setTableName(join.getRightTable());
|
// set up the query - for the table on the right side of the join //
|
||||||
queryInput.setShouldTranslatePossibleValues(true);
|
////////////////////////////////////////////////////////////////////
|
||||||
queryInput.setShouldGenerateDisplayValues(true);
|
filter = new QQueryFilter();
|
||||||
queryInput.setFilter(filter);
|
for(JoinOn joinOn : join.getJoinOns())
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
{
|
||||||
|
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();
|
QValueFormatter.setBlobValuesToDownloadUrls(rightTable, queryOutput.getRecords());
|
||||||
if(maxRows != null && (queryOutput.getRecords().size() == maxRows))
|
|
||||||
{
|
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> //
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
// if the input said to only do some max, and the # of results we got is that max, //
|
||||||
CountInput countInput = new CountInput();
|
// then do a count query, for displaying 1-n of <count> //
|
||||||
countInput.setTableName(join.getRightTable());
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
countInput.setFilter(filter);
|
CountInput countInput = new CountInput();
|
||||||
totalRows = new CountAction().execute(countInput).getCount();
|
countInput.setTableName(join.getRightTable());
|
||||||
|
countInput.setFilter(filter);
|
||||||
|
totalRows = new CountAction().execute(countInput).getCount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String tablePath = input.getInstance().getTablePath(rightTable.getName());
|
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 //
|
// new child records must have values from the join-ons //
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
Map<String, Serializable> defaultValuesForNewChildRecords = new HashMap<>();
|
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);
|
widgetData.setDefaultValuesForNewChildRecords(defaultValuesForNewChildRecords);
|
||||||
|
|
||||||
Map<String, Serializable> widgetValues = input.getWidgetMetaData().getDefaultValues();
|
Map<String, Serializable> widgetValues = input.getWidgetMetaData().getDefaultValues();
|
||||||
@ -250,6 +273,22 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
|||||||
{
|
{
|
||||||
widgetData.setDisabledFieldsForNewChildRecords((Set<String>) widgetValues.get("disabledFieldsForNewChildRecords"));
|
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));
|
return (new RenderWidgetOutput(widgetData));
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
@ -60,6 +61,7 @@ public class QFrontendWidgetMetaData
|
|||||||
|
|
||||||
protected Map<String, QIcon> icons;
|
protected Map<String, QIcon> icons;
|
||||||
protected Map<String, QHelpContent> helpContent;
|
protected Map<String, QHelpContent> helpContent;
|
||||||
|
protected Map<String, Serializable> defaultValues;
|
||||||
|
|
||||||
private final boolean hasPermission;
|
private final boolean hasPermission;
|
||||||
|
|
||||||
@ -95,6 +97,7 @@ public class QFrontendWidgetMetaData
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.helpContent = widgetMetaData.getHelpContent();
|
this.helpContent = widgetMetaData.getHelpContent();
|
||||||
|
this.defaultValues = widgetMetaData.getDefaultValues();
|
||||||
|
|
||||||
hasPermission = PermissionsHelper.hasWidgetPermission(actionInput, name);
|
hasPermission = PermissionsHelper.hasWidgetPermission(actionInput, name);
|
||||||
}
|
}
|
||||||
@ -274,4 +277,16 @@ public class QFrontendWidgetMetaData
|
|||||||
{
|
{
|
||||||
return helpContent;
|
return helpContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for defaultValues
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, Serializable> getDefaultValues()
|
||||||
|
{
|
||||||
|
return defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -779,9 +779,30 @@ public class QJavalinImplementation
|
|||||||
{
|
{
|
||||||
String fieldName = formParam.getKey();
|
String fieldName = formParam.getKey();
|
||||||
List<String> values = formParam.getValue();
|
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))
|
if(CollectionUtils.nullSafeHasContents(values))
|
||||||
{
|
{
|
||||||
String value = values.get(0);
|
|
||||||
if(StringUtils.hasContent(value))
|
if(StringUtils.hasContent(value))
|
||||||
{
|
{
|
||||||
record.setValue(fieldName, value);
|
record.setValue(fieldName, value);
|
||||||
|
Reference in New Issue
Block a user