Moving dropdowns to work for all widgets

This commit is contained in:
2022-12-09 09:53:13 -06:00
parent 8454f94020
commit 14c7fbe370
26 changed files with 576 additions and 521 deletions

View File

@ -39,6 +39,7 @@ import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat; import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
/******************************************************************************* /*******************************************************************************
@ -173,7 +174,7 @@ public abstract class AbstractHTMLWidgetRenderer extends AbstractWidgetRenderer
public static String aHrefTableFilterNoOfRecords(RenderWidgetInput input, String tableName, QQueryFilter filter, Integer noOfRecords, String singularLabel, String pluralLabel) throws QException public static String aHrefTableFilterNoOfRecords(RenderWidgetInput input, String tableName, QQueryFilter filter, Integer noOfRecords, String singularLabel, String pluralLabel) throws QException
{ {
String href = linkTableFilter(input, tableName, filter); String href = linkTableFilter(input, tableName, filter);
return ("<a href=\"" + href + "\">" + QValueFormatter.formatValue(DisplayFormat.COMMAS, noOfRecords) + " " + pluralize(noOfRecords, singularLabel, pluralLabel) + "</a>"); return ("<a href=\"" + href + "\">" + QValueFormatter.formatValue(DisplayFormat.COMMAS, noOfRecords) + " " + StringUtils.plural(noOfRecords, singularLabel, pluralLabel) + "</a>");
} }
@ -265,19 +266,4 @@ public abstract class AbstractHTMLWidgetRenderer extends AbstractWidgetRenderer
return ("<a href=\"" + linkTableCreateChild(childTableName, defaultValues, defaultValues.keySet()) + "\">Create new</a>"); return ("<a href=\"" + linkTableCreateChild(childTableName, defaultValues, defaultValues.keySet()) + "\">Create new</a>");
} }
/*******************************************************************************
**
*******************************************************************************/
public static String pluralize(Integer count, String singular, String plural)
{
if(count != null && count.equals(1))
{
return (singular);
}
return (plural);
}
} }

View File

@ -24,10 +24,29 @@ package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter; import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
import com.kingsrook.qqq.backend.core.actions.values.SearchPossibleValueSourceAction;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidgetData;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.WidgetDropdownData;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
/******************************************************************************* /*******************************************************************************
@ -46,4 +65,103 @@ public abstract class AbstractWidgetRenderer
*******************************************************************************/ *******************************************************************************/
public abstract RenderWidgetOutput render(RenderWidgetInput input) throws QException; public abstract RenderWidgetOutput render(RenderWidgetInput input) throws QException;
/*******************************************************************************
**
*******************************************************************************/
protected boolean setupDropdowns(RenderWidgetInput input, QWidgetMetaData metaData, QWidgetData widgetData) throws QException
{
List<List<Map<String, String>>> pvsData = new ArrayList<>();
List<String> pvsLabels = new ArrayList<>();
List<String> pvsNames = new ArrayList<>();
List<String> missingRequiredSelections = new ArrayList<>();
for(WidgetDropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
{
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// this looks complicated, but is just look for a label in the dropdown data and if found use it, //
// otherwise look for label in PVS and if found use that, otherwise just use the PVS name //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
String pvsLabel = dropdownData.getLabel() != null ? dropdownData.getLabel() : (possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName);
pvsLabels.add(pvsLabel);
pvsNames.add(possibleValueSourceName);
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
pvsInput.setSession(input.getSession());
pvsInput.setPossibleValueSourceName(possibleValueSourceName);
if(dropdownData.getForeignKeyFieldName() != null)
{
////////////////////////////////////////
// look for an id in the query params //
////////////////////////////////////////
Integer id = null;
if(input.getQueryParams() != null && input.getQueryParams().containsKey("id") && StringUtils.hasContent(input.getQueryParams().get("id")))
{
id = Integer.parseInt(input.getQueryParams().get("id"));
}
if(id != null)
{
pvsInput.setDefaultQueryFilter(new QQueryFilter().withCriteria(
new QFilterCriteria(
dropdownData.getForeignKeyFieldName(),
QCriteriaOperator.EQUALS,
id)));
}
}
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceAction().execute(pvsInput);
List<Map<String, String>> dropdownOptionList = new ArrayList<>();
pvsData.add(dropdownOptionList);
//////////////////////////////////////////
// sort results, dedupe, and add to map //
//////////////////////////////////////////
Set<String> exists = new HashSet<>();
output.getResults().removeIf(pvs -> !exists.add(pvs.getLabel()));
output.getResults().sort(Comparator.comparing(QPossibleValue::getLabel));
for(QPossibleValue<?> possibleValue : output.getResults())
{
dropdownOptionList.add(Map.of(
"id", String.valueOf(possibleValue.getId()),
"label", possibleValue.getLabel()
));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// because we know the dropdowns and what the field names will be when something is selected, we can make //
// sure that something has been selected, and if not, display a message that a selection needs made //
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(dropdownData.getIsRequired())
{
if(!input.getQueryParams().containsKey(possibleValueSourceName) || !StringUtils.hasContent(input.getQueryParams().get(possibleValueSourceName)))
{
missingRequiredSelections.add(pvsLabel);
}
}
}
widgetData.setDropdownNameList(pvsNames);
widgetData.setDropdownLabelList(pvsLabels);
widgetData.setDropdownDataList(pvsData);
////////////////////////////////////////////////////////////////////////////////
// if there are any missing required dropdowns, build up a message to display //
////////////////////////////////////////////////////////////////////////////////
if(missingRequiredSelections.size() > 0)
{
StringBuilder sb = new StringBuilder("Please select a ").append(StringUtils.joinWithCommasAndAnd(missingRequiredSelections));
sb.append(" from the ").append(StringUtils.plural(missingRequiredSelections.size(), "dropdown", "dropdowns")).append(" above.");
widgetData.setDropdownNeedsSelectedText(sb.toString());
return (false);
}
else
{
return (true);
}
}
} }

View File

@ -22,28 +22,12 @@
package com.kingsrook.qqq.backend.core.actions.dashboard.widgets; package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.kingsrook.qqq.backend.core.actions.ActionHelper; import com.kingsrook.qqq.backend.core.actions.ActionHelper;
import com.kingsrook.qqq.backend.core.actions.values.SearchPossibleValueSourceAction;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.ParentWidgetData; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.ParentWidgetData;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
/******************************************************************************* /*******************************************************************************
@ -69,93 +53,9 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// handle any PVSs creating dropdown data for the frontend // // handle any PVSs creating dropdown data for the frontend //
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
List<List<Map<String, String>>> pvsData = new ArrayList<>(); boolean dropdownsValid = setupDropdowns(input, metaData, widgetData);
List<String> pvsLabels = new ArrayList<>();
List<String> pvsNames = new ArrayList<>();
List<String> missingRequiredSelections = new ArrayList<>();
for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
{
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(dropdownsValid)
// this looks complicated, but is just look for a label in the dropdown data and if found use it, //
// otherwise look for label in PVS and if found use that, otherwise just use the PVS name //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
String pvsLabel = dropdownData.getLabel() != null ? dropdownData.getLabel() : (possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName);
pvsLabels.add(pvsLabel);
pvsNames.add(possibleValueSourceName);
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
pvsInput.setSession(input.getSession());
pvsInput.setPossibleValueSourceName(possibleValueSourceName);
if(dropdownData.getForeignKeyFieldName() != null)
{
////////////////////////////////////////
// look for an id in the query params //
////////////////////////////////////////
Integer id = null;
if(input.getQueryParams() != null && input.getQueryParams().containsKey("id") && StringUtils.hasContent(input.getQueryParams().get("id")))
{
id = Integer.parseInt(input.getQueryParams().get("id"));
}
if(id != null)
{
pvsInput.setDefaultQueryFilter(new QQueryFilter().withCriteria(
new QFilterCriteria(
dropdownData.getForeignKeyFieldName(),
QCriteriaOperator.EQUALS,
id)));
}
}
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceAction().execute(pvsInput);
List<Map<String, String>> dropdownOptionList = new ArrayList<>();
pvsData.add(dropdownOptionList);
//////////////////////////////////////////
// sort results, dedupe, and add to map //
//////////////////////////////////////////
Set<String> exists = new HashSet<>();
output.getResults().removeIf(pvs -> !exists.add(pvs.getLabel()));
output.getResults().sort(Comparator.comparing(QPossibleValue::getLabel));
for(QPossibleValue<?> possibleValue : output.getResults())
{
dropdownOptionList.add(Map.of(
"id", String.valueOf(possibleValue.getId()),
"label", possibleValue.getLabel()
));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// because we know the dropdowns and what the field names will be when something is selected, we can make //
// sure that something has been selected, and if not, display a message that a selection needs made //
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(dropdownData.getIsRequired())
{
if(!input.getQueryParams().containsKey(possibleValueSourceName) || !StringUtils.hasContent(input.getQueryParams().get(possibleValueSourceName)))
{
missingRequiredSelections.add(pvsLabel);
}
}
}
widgetData.setDropdownNameList(pvsNames);
widgetData.setDropdownLabelList(pvsLabels);
widgetData.setDropdownDataList(pvsData);
////////////////////////////////////////////////////////////////////////////////
// if there are any missing required dropdowns, build up a message to display //
////////////////////////////////////////////////////////////////////////////////
if(missingRequiredSelections.size() > 0)
{
StringBuilder sb = new StringBuilder("Please select a ").append(StringUtils.joinWithCommasAndAnd(missingRequiredSelections));
sb.append(" from the ").append(StringUtils.plural(missingRequiredSelections.size(), "dropdown", "dropdowns")).append(" above.");
widgetData.setDropdownNeedsSelectedText(sb.toString());
}
else
{ {
widgetData.setChildWidgetNameList(metaData.getChildWidgetNameList()); widgetData.setChildWidgetNameList(metaData.getChildWidgetNameList());
} }

View File

@ -22,6 +22,7 @@
package com.kingsrook.qqq.backend.core.actions.dashboard.widgets; package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
import java.util.HashMap;
import com.kingsrook.qqq.backend.core.actions.ActionHelper; import com.kingsrook.qqq.backend.core.actions.ActionHelper;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
@ -53,9 +54,14 @@ public class ProcessWidgetRenderer extends AbstractWidgetRenderer
ProcessWidgetData data = new ProcessWidgetData(); ProcessWidgetData data = new ProcessWidgetData();
if(input.getWidgetMetaData() instanceof QWidgetMetaData widgetMetaData) if(input.getWidgetMetaData() instanceof QWidgetMetaData widgetMetaData)
{ {
setupDropdowns(input, widgetMetaData, data);
// todo - something about an error-like screen if dropdowns aren't valid?
String processName = (String) widgetMetaData.getDefaultValues().get(WIDGET_PROCESS_NAME); String processName = (String) widgetMetaData.getDefaultValues().get(WIDGET_PROCESS_NAME);
QProcessMetaData processMetaData = input.getInstance().getProcess(processName); QProcessMetaData processMetaData = input.getInstance().getProcess(processName);
data.setProcessMetaData(processMetaData); data.setProcessMetaData(processMetaData);
data.setDefaultValues(new HashMap<>(input.getQueryParams()));
} }
return (new RenderWidgetOutput(data)); return (new RenderWidgetOutput(data));
} }

View File

@ -26,7 +26,7 @@ import com.kingsrook.qqq.backend.core.actions.ActionHelper;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidget; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidgetData;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QuickSightChart; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QuickSightChart;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QuickSightChartMetaData; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QuickSightChartMetaData;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
@ -75,7 +75,7 @@ public class QuickSightChartRenderer extends AbstractWidgetRenderer
final GenerateEmbedUrlForRegisteredUserResponse generateEmbedUrlForRegisteredUserResponse = quickSightClient.generateEmbedUrlForRegisteredUser(generateEmbedUrlForRegisteredUserRequest); final GenerateEmbedUrlForRegisteredUserResponse generateEmbedUrlForRegisteredUserResponse = quickSightClient.generateEmbedUrlForRegisteredUser(generateEmbedUrlForRegisteredUserRequest);
String embedUrl = generateEmbedUrlForRegisteredUserResponse.embedUrl(); String embedUrl = generateEmbedUrlForRegisteredUserResponse.embedUrl();
QWidget widget = new QuickSightChart(input.getWidgetMetaData().getName(), quickSightMetaData.getLabel(), embedUrl); QWidgetData widget = new QuickSightChart(input.getWidgetMetaData().getName(), quickSightMetaData.getLabel(), embedUrl);
return (new RenderWidgetOutput(widget)); return (new RenderWidgetOutput(widget));
} }
catch(Exception e) catch(Exception e)

View File

@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.model.actions.widgets;
import java.io.Serializable; import java.io.Serializable;
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidgetData;
/******************************************************************************* /*******************************************************************************
@ -30,7 +31,7 @@ import java.io.Serializable;
*******************************************************************************/ *******************************************************************************/
public class RenderWidgetOutput implements Serializable public class RenderWidgetOutput implements Serializable
{ {
public Object widgetData; public QWidgetData widgetData;
@ -38,7 +39,7 @@ public class RenderWidgetOutput implements Serializable
** constructor taking in widget data ** constructor taking in widget data
** **
*******************************************************************************/ *******************************************************************************/
public RenderWidgetOutput(Object widgetData) public RenderWidgetOutput(QWidgetData widgetData)
{ {
this.widgetData = widgetData; this.widgetData = widgetData;
} }
@ -49,7 +50,7 @@ public class RenderWidgetOutput implements Serializable
** Getter for widgetData ** Getter for widgetData
** **
*******************************************************************************/ *******************************************************************************/
public Object getWidgetData() public QWidgetData getWidgetData()
{ {
return widgetData; return widgetData;
} }
@ -60,7 +61,7 @@ public class RenderWidgetOutput implements Serializable
** Setter for widgetData ** Setter for widgetData
** **
*******************************************************************************/ *******************************************************************************/
public void setWidgetData(Object widgetData) public void setWidgetData(QWidgetData widgetData)
{ {
this.widgetData = widgetData; this.widgetData = widgetData;
} }
@ -71,7 +72,7 @@ public class RenderWidgetOutput implements Serializable
** Fluent setter for widgetData ** Fluent setter for widgetData
** **
*******************************************************************************/ *******************************************************************************/
public RenderWidgetOutput withWidgetData(Object widgetData) public RenderWidgetOutput withWidgetData(QWidgetData widgetData)
{ {
this.widgetData = widgetData; this.widgetData = widgetData;
return (this); return (this);

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget ** Model containing datastructure expected by frontend bar chart widget
** **
*******************************************************************************/ *******************************************************************************/
public class ChartData implements QWidget public class ChartData extends QWidgetData
{ {
/* /*
interface BarChartData{ interface BarChartData{

View File

@ -33,7 +33,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
** Model containing data structure expected by frontend ChildRecordList widget ** Model containing data structure expected by frontend ChildRecordList widget
** **
*******************************************************************************/ *******************************************************************************/
public class ChildRecordListData implements QWidget public class ChildRecordListData extends QWidgetData
{ {
private String title; private String title;
private QueryOutput queryOutput; private QueryOutput queryOutput;

View File

@ -26,7 +26,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
** Model containing datastructure expected by frontend divider widget ** Model containing datastructure expected by frontend divider widget
** **
*******************************************************************************/ *******************************************************************************/
public class DividerWidgetData implements QWidget public class DividerWidgetData extends QWidgetData
{ {
/******************************************************************************* /*******************************************************************************
** **

View File

@ -40,7 +40,7 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
** Model containing data structure expected by frontend FieldValueListData widget ** Model containing data structure expected by frontend FieldValueListData widget
** **
*******************************************************************************/ *******************************************************************************/
public class FieldValueListData implements QWidget public class FieldValueListData extends QWidgetData
{ {
private List<QFieldMetaData> fields; private List<QFieldMetaData> fields;
private QRecord record; private QRecord record;

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget ** Model containing datastructure expected by frontend bar chart widget
** **
*******************************************************************************/ *******************************************************************************/
public class LineChartData implements QWidget public class LineChartData extends QWidgetData
{ {
/* /*
export interface DefaultLineChartData export interface DefaultLineChartData

View File

@ -26,7 +26,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
** Model containing datastructure expected by frontend location widget ** Model containing datastructure expected by frontend location widget
** **
*******************************************************************************/ *******************************************************************************/
public class LocationData implements QWidget public class LocationData extends QWidgetData
{ {
private String imageUrl; private String imageUrl;
private String title; private String title;

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget ** Model containing datastructure expected by frontend bar chart widget
** **
*******************************************************************************/ *******************************************************************************/
public class MultiStatisticsData implements QWidget public class MultiStatisticsData extends QWidgetData
{ {
private String title; private String title;
private List<StatisticsGroupData> statisticsGroupData; private List<StatisticsGroupData> statisticsGroupData;

View File

@ -23,27 +23,15 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
import java.util.List; import java.util.List;
import java.util.Map;
/******************************************************************************* /*******************************************************************************
** Model containing datastructure expected by frontend parent widget ** Model containing datastructure expected by frontend parent widget
** **
*******************************************************************************/ *******************************************************************************/
public class ParentWidgetData implements QWidget public class ParentWidgetData extends QWidgetData
{ {
private List<String> dropdownNameList;
private List<String> dropdownLabelList;
/////////////////////////////////////////////////////////////////////////////////////////
// this is a list of lists, the outer list corresponds to each dropdown (parallel list //
// with the above dropdownLabelList) - the inner list is the list of actual dropdown //
// options //
/////////////////////////////////////////////////////////////////////////////////////////
private List<List<Map<String, String>>> dropdownDataList;
private List<String> childWidgetNameList; private List<String> childWidgetNameList;
private String dropdownNeedsSelectedText;
@ -67,108 +55,6 @@ public class ParentWidgetData implements QWidget
/*******************************************************************************
** Getter for dropdownLabelList
**
*******************************************************************************/
public List<String> getDropdownLabelList()
{
return dropdownLabelList;
}
/*******************************************************************************
** Setter for dropdownLabelList
**
*******************************************************************************/
public void setDropdownLabelList(List<String> dropdownLabelList)
{
this.dropdownLabelList = dropdownLabelList;
}
/*******************************************************************************
** Fluent setter for dropdownLabelList
**
*******************************************************************************/
public ParentWidgetData withDropdownLabelList(List<String> dropdownLabelList)
{
this.dropdownLabelList = dropdownLabelList;
return (this);
}
/*******************************************************************************
** Getter for dropdownNameList
**
*******************************************************************************/
public List<String> getDropdownNameList()
{
return dropdownNameList;
}
/*******************************************************************************
** Setter for dropdownNameList
**
*******************************************************************************/
public void setDropdownNameList(List<String> dropdownNameList)
{
this.dropdownNameList = dropdownNameList;
}
/*******************************************************************************
** Fluent setter for dropdownNameList
**
*******************************************************************************/
public ParentWidgetData withDropdownNameList(List<String> dropdownNameList)
{
this.dropdownNameList = dropdownNameList;
return (this);
}
/*******************************************************************************
** Getter for dropdownDataList
**
*******************************************************************************/
public List<List<Map<String, String>>> getDropdownDataList()
{
return dropdownDataList;
}
/*******************************************************************************
** Setter for dropdownDataList
**
*******************************************************************************/
public void setDropdownDataList(List<List<Map<String, String>>> dropdownDataList)
{
this.dropdownDataList = dropdownDataList;
}
/*******************************************************************************
** Fluent setter for dropdownDataList
**
*******************************************************************************/
public ParentWidgetData withDropdownDataList(List<List<Map<String, String>>> dropdownDataList)
{
this.dropdownDataList = dropdownDataList;
return (this);
}
/******************************************************************************* /*******************************************************************************
** Getter for childWidgetNameList ** Getter for childWidgetNameList
** **
@ -201,38 +87,4 @@ public class ParentWidgetData implements QWidget
return (this); return (this);
} }
/*******************************************************************************
** Getter for dropdownNeedsSelectedText
**
*******************************************************************************/
public String getDropdownNeedsSelectedText()
{
return dropdownNeedsSelectedText;
}
/*******************************************************************************
** Setter for dropdownNeedsSelectedText
**
*******************************************************************************/
public void setDropdownNeedsSelectedText(String dropdownNeedsSelectedText)
{
this.dropdownNeedsSelectedText = dropdownNeedsSelectedText;
}
/*******************************************************************************
** Fluent setter for dropdownNeedsSelectedText
**
*******************************************************************************/
public ParentWidgetData withDropdownNeedsSelectedText(String dropdownNeedsSelectedText)
{
this.dropdownNeedsSelectedText = dropdownNeedsSelectedText;
return (this);
}
} }

View File

@ -31,7 +31,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
** Model containing datastructure expected by frontend process widget ** Model containing datastructure expected by frontend process widget
** **
*******************************************************************************/ *******************************************************************************/
public class ProcessWidgetData implements QWidget public class ProcessWidgetData extends QWidgetData
{ {
private QProcessMetaData processMetaData; private QProcessMetaData processMetaData;
private Map<String, Serializable> defaultValues; private Map<String, Serializable> defaultValues;

View File

@ -1,36 +0,0 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
/*******************************************************************************
** Interface for frontend widget's datastructures
**
*******************************************************************************/
public interface QWidget
{
/*******************************************************************************
** Getter for type
*******************************************************************************/
String getType();
}

View File

@ -0,0 +1,188 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
import java.util.List;
import java.util.Map;
/*******************************************************************************
** Base class for the data returned by rendering a Widget.
**
*******************************************************************************/
public abstract class QWidgetData
{
private List<String> dropdownNameList;
private List<String> dropdownLabelList;
/////////////////////////////////////////////////////////////////////////////////////////
// this is a list of lists, the outer list corresponds to each dropdown (parallel list //
// with the above dropdownLabelList) - the inner list is the list of actual dropdown //
// options //
/////////////////////////////////////////////////////////////////////////////////////////
private List<List<Map<String, String>>> dropdownDataList;
private String dropdownNeedsSelectedText;
/*******************************************************************************
** Getter for type
*******************************************************************************/
public abstract String getType();
/*******************************************************************************
** Getter for dropdownLabelList
**
*******************************************************************************/
public List<String> getDropdownLabelList()
{
return dropdownLabelList;
}
/*******************************************************************************
** Setter for dropdownLabelList
**
*******************************************************************************/
public void setDropdownLabelList(List<String> dropdownLabelList)
{
this.dropdownLabelList = dropdownLabelList;
}
/*******************************************************************************
** Fluent setter for dropdownLabelList
**
*******************************************************************************/
public QWidgetData withDropdownLabelList(List<String> dropdownLabelList)
{
this.dropdownLabelList = dropdownLabelList;
return (this);
}
/*******************************************************************************
** Getter for dropdownNameList
**
*******************************************************************************/
public List<String> getDropdownNameList()
{
return dropdownNameList;
}
/*******************************************************************************
** Setter for dropdownNameList
**
*******************************************************************************/
public void setDropdownNameList(List<String> dropdownNameList)
{
this.dropdownNameList = dropdownNameList;
}
/*******************************************************************************
** Fluent setter for dropdownNameList
**
*******************************************************************************/
public QWidgetData withDropdownNameList(List<String> dropdownNameList)
{
this.dropdownNameList = dropdownNameList;
return (this);
}
/*******************************************************************************
** Getter for dropdownDataList
**
*******************************************************************************/
public List<List<Map<String, String>>> getDropdownDataList()
{
return dropdownDataList;
}
/*******************************************************************************
** Setter for dropdownDataList
**
*******************************************************************************/
public void setDropdownDataList(List<List<Map<String, String>>> dropdownDataList)
{
this.dropdownDataList = dropdownDataList;
}
/*******************************************************************************
** Fluent setter for dropdownDataList
**
*******************************************************************************/
public QWidgetData withDropdownDataList(List<List<Map<String, String>>> dropdownDataList)
{
this.dropdownDataList = dropdownDataList;
return (this);
}
/*******************************************************************************
** Getter for dropdownNeedsSelectedText
**
*******************************************************************************/
public String getDropdownNeedsSelectedText()
{
return dropdownNeedsSelectedText;
}
/*******************************************************************************
** Setter for dropdownNeedsSelectedText
**
*******************************************************************************/
public void setDropdownNeedsSelectedText(String dropdownNeedsSelectedText)
{
this.dropdownNeedsSelectedText = dropdownNeedsSelectedText;
}
/*******************************************************************************
** Fluent setter for dropdownNeedsSelectedText
**
*******************************************************************************/
public QWidgetData withDropdownNeedsSelectedText(String dropdownNeedsSelectedText)
{
this.dropdownNeedsSelectedText = dropdownNeedsSelectedText;
return (this);
}
}

View File

@ -27,7 +27,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
** TODO: this might just be an IFrameChart widget in the future ** TODO: this might just be an IFrameChart widget in the future
** **
*******************************************************************************/ *******************************************************************************/
public class QuickSightChart implements QWidget public class QuickSightChart extends QWidgetData
{ {
private String label; private String label;
private String name; private String name;

View File

@ -26,7 +26,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
** Model containing datastructure expected by frontend bar raw html widget ** Model containing datastructure expected by frontend bar raw html widget
** **
*******************************************************************************/ *******************************************************************************/
public class RawHTML implements QWidget public class RawHTML extends QWidgetData
{ {
private String title; private String title;
private String html; private String html;

View File

@ -26,7 +26,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
** Model containing datastructure expected by frontend bar chart widget ** Model containing datastructure expected by frontend bar chart widget
** **
*******************************************************************************/ *******************************************************************************/
public class StatisticsData implements QWidget public class StatisticsData extends QWidgetData
{ {
/* /*
interface BarChartData{ interface BarChartData{

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend stepper widget ** Model containing datastructure expected by frontend stepper widget
** **
*******************************************************************************/ *******************************************************************************/
public class StepperData implements QWidget public class StepperData extends QWidgetData
{ {
private String title; private String title;
private int activeStep; private int activeStep;

View File

@ -30,7 +30,7 @@ import java.util.Map;
** Model containing datastructure expected by frontend bar chart widget ** Model containing datastructure expected by frontend bar chart widget
** **
*******************************************************************************/ *******************************************************************************/
public class TableData implements QWidget public class TableData extends QWidgetData
{ {
private String title; private String title;
private String linkText; private String linkText;

View File

@ -34,7 +34,6 @@ public class ParentWidgetMetaData extends QWidgetMetaData
private String title; private String title;
private List<String> childWidgetNameList; private List<String> childWidgetNameList;
private List<String> childProcessNameList; private List<String> childProcessNameList;
private List<DropdownData> dropdowns;
@ -138,189 +137,4 @@ public class ParentWidgetMetaData extends QWidgetMetaData
return (this); return (this);
} }
/*******************************************************************************
** Getter for dropdowns
**
*******************************************************************************/
public List<DropdownData> getDropdowns()
{
return dropdowns;
}
/*******************************************************************************
** Setter for dropdowns
**
*******************************************************************************/
public void setDropdowns(List<DropdownData> dropdowns)
{
this.dropdowns = dropdowns;
}
/*******************************************************************************
** Fluent setter for dropdowns
**
*******************************************************************************/
public ParentWidgetMetaData withDropdowns(List<DropdownData> dropdowns)
{
this.dropdowns = dropdowns;
return (this);
}
/*******************************************************************************
** inner class for specifying details about dropdown fields on a parent widget
**
*******************************************************************************/
public static class DropdownData
{
private String possibleValueSourceName;
private String foreignKeyFieldName;
private String label;
private boolean isRequired;
/*******************************************************************************
** Getter for possibleValueSourceName
**
*******************************************************************************/
public String getPossibleValueSourceName()
{
return possibleValueSourceName;
}
/*******************************************************************************
** Setter for possibleValueSourceName
**
*******************************************************************************/
public void setPossibleValueSourceName(String possibleValueSourceName)
{
this.possibleValueSourceName = possibleValueSourceName;
}
/*******************************************************************************
** Fluent setter for possibleValueSourceName
**
*******************************************************************************/
public DropdownData withPossibleValueSourceName(String possibleValueSourceName)
{
this.possibleValueSourceName = possibleValueSourceName;
return (this);
}
/*******************************************************************************
** Getter for foreignKeyFieldName
**
*******************************************************************************/
public String getForeignKeyFieldName()
{
return foreignKeyFieldName;
}
/*******************************************************************************
** Setter for foreignKeyFieldName
**
*******************************************************************************/
public void setForeignKeyFieldName(String foreignKeyFieldName)
{
this.foreignKeyFieldName = foreignKeyFieldName;
}
/*******************************************************************************
** Fluent setter for foreignKeyFieldName
**
*******************************************************************************/
public DropdownData withForeignKeyFieldName(String foreignKeyFieldName)
{
this.foreignKeyFieldName = foreignKeyFieldName;
return (this);
}
/*******************************************************************************
** Getter for label
**
*******************************************************************************/
public String getLabel()
{
return label;
}
/*******************************************************************************
** Setter for label
**
*******************************************************************************/
public void setLabel(String label)
{
this.label = label;
}
/*******************************************************************************
** Fluent setter for label
**
*******************************************************************************/
public DropdownData withLabel(String label)
{
this.label = label;
return (this);
}
/*******************************************************************************
** Getter for isRequired
**
*******************************************************************************/
public boolean getIsRequired()
{
return isRequired;
}
/*******************************************************************************
** Setter for isRequired
**
*******************************************************************************/
public void setIsRequired(boolean isRequired)
{
this.isRequired = isRequired;
}
/*******************************************************************************
** Fluent setter for isRequired
**
*******************************************************************************/
public DropdownData withIsRequired(boolean isRequired)
{
this.isRequired = isRequired;
return (this);
}
}
} }

View File

@ -23,7 +23,9 @@ package com.kingsrook.qqq.backend.core.model.metadata.dashboard;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
@ -41,6 +43,7 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
protected Integer gridColumns; protected Integer gridColumns;
protected QCodeReference codeReference; protected QCodeReference codeReference;
private List<WidgetDropdownData> dropdowns;
protected Map<String, Serializable> defaultValues = new LinkedHashMap<>(); protected Map<String, Serializable> defaultValues = new LinkedHashMap<>();
@ -299,4 +302,54 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
return (this); return (this);
} }
/*******************************************************************************
** Getter for dropdowns
**
*******************************************************************************/
public List<WidgetDropdownData> getDropdowns()
{
return dropdowns;
}
/*******************************************************************************
** Setter for dropdowns
**
*******************************************************************************/
public void setDropdowns(List<WidgetDropdownData> dropdowns)
{
this.dropdowns = dropdowns;
}
/*******************************************************************************
** Fluent setter for dropdowns
**
*******************************************************************************/
public QWidgetMetaData withDropdowns(List<WidgetDropdownData> dropdowns)
{
this.dropdowns = dropdowns;
return (this);
}
/*******************************************************************************
** Fluent setter for dropdowns
**
*******************************************************************************/
public QWidgetMetaData withDropdown(WidgetDropdownData dropdown)
{
if(this.dropdowns == null)
{
this.dropdowns = new ArrayList<>();
}
this.dropdowns.add(dropdown);
return (this);
}
} }

View File

@ -0,0 +1,172 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.metadata.dashboard;
/*******************************************************************************
** inner class for specifying details about dropdown fields on a parent widget
**
*******************************************************************************/
public class WidgetDropdownData
{
private String possibleValueSourceName;
private String foreignKeyFieldName;
private String label;
private boolean isRequired;
/*******************************************************************************
** Getter for possibleValueSourceName
**
*******************************************************************************/
public String getPossibleValueSourceName()
{
return possibleValueSourceName;
}
/*******************************************************************************
** Setter for possibleValueSourceName
**
*******************************************************************************/
public void setPossibleValueSourceName(String possibleValueSourceName)
{
this.possibleValueSourceName = possibleValueSourceName;
}
/*******************************************************************************
** Fluent setter for possibleValueSourceName
**
*******************************************************************************/
public WidgetDropdownData withPossibleValueSourceName(String possibleValueSourceName)
{
this.possibleValueSourceName = possibleValueSourceName;
return (this);
}
/*******************************************************************************
** Getter for foreignKeyFieldName
**
*******************************************************************************/
public String getForeignKeyFieldName()
{
return foreignKeyFieldName;
}
/*******************************************************************************
** Setter for foreignKeyFieldName
**
*******************************************************************************/
public void setForeignKeyFieldName(String foreignKeyFieldName)
{
this.foreignKeyFieldName = foreignKeyFieldName;
}
/*******************************************************************************
** Fluent setter for foreignKeyFieldName
**
*******************************************************************************/
public WidgetDropdownData withForeignKeyFieldName(String foreignKeyFieldName)
{
this.foreignKeyFieldName = foreignKeyFieldName;
return (this);
}
/*******************************************************************************
** Getter for label
**
*******************************************************************************/
public String getLabel()
{
return label;
}
/*******************************************************************************
** Setter for label
**
*******************************************************************************/
public void setLabel(String label)
{
this.label = label;
}
/*******************************************************************************
** Fluent setter for label
**
*******************************************************************************/
public WidgetDropdownData withLabel(String label)
{
this.label = label;
return (this);
}
/*******************************************************************************
** Getter for isRequired
**
*******************************************************************************/
public boolean getIsRequired()
{
return isRequired;
}
/*******************************************************************************
** Setter for isRequired
**
*******************************************************************************/
public void setIsRequired(boolean isRequired)
{
this.isRequired = isRequired;
}
/*******************************************************************************
** Fluent setter for isRequired
**
*******************************************************************************/
public WidgetDropdownData withIsRequired(boolean isRequired)
{
this.isRequired = isRequired;
return (this);
}
}

View File

@ -38,6 +38,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.WidgetDropdownData;
import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.model.session.QSession;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore; import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
@ -75,19 +76,19 @@ class ParentWidgetRendererTest
QWidgetMetaDataInterface parentWidget = new ParentWidgetMetaData() QWidgetMetaDataInterface parentWidget = new ParentWidgetMetaData()
.withTitle("Parent") .withTitle("Parent")
.withDropdowns(
List.of(
new ParentWidgetMetaData.DropdownData()
.withPossibleValueSourceName(TestUtils.defineStatesPossibleValueSource().getName()),
new ParentWidgetMetaData.DropdownData()
.withPossibleValueSourceName(TestUtils.defineShapePossibleValueSource().getName())
)
)
.withChildWidgetNameList( .withChildWidgetNameList(
List.of( List.of(
ProcessWidgetRenderer.class.getSimpleName() ProcessWidgetRenderer.class.getSimpleName()
) )
) )
.withDropdowns(
List.of(
new WidgetDropdownData()
.withPossibleValueSourceName(TestUtils.defineStatesPossibleValueSource().getName()),
new WidgetDropdownData()
.withPossibleValueSourceName(TestUtils.defineShapePossibleValueSource().getName())
)
)
.withType(WidgetType.PARENT_WIDGET.getType()) .withType(WidgetType.PARENT_WIDGET.getType())
.withName(ProcessWidgetRenderer.class.getSimpleName()) .withName(ProcessWidgetRenderer.class.getSimpleName())
.withGridColumns(12) .withGridColumns(12)