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.processes.QProcessMetaData;
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
{
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>");
}
/*******************************************************************************
**
*******************************************************************************/
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.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.SearchPossibleValueSourceAction;
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.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;
/*******************************************************************************
**
*******************************************************************************/
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;
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.values.SearchPossibleValueSourceAction;
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.RenderWidgetOutput;
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.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 //
/////////////////////////////////////////////////////////////
List<List<Map<String, String>>> pvsData = new ArrayList<>();
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);
boolean dropdownsValid = setupDropdowns(input, metaData, widgetData);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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
if(dropdownsValid)
{
widgetData.setChildWidgetNameList(metaData.getChildWidgetNameList());
}

View File

@ -22,6 +22,7 @@
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.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
@ -53,9 +54,14 @@ public class ProcessWidgetRenderer extends AbstractWidgetRenderer
ProcessWidgetData data = new ProcessWidgetData();
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);
QProcessMetaData processMetaData = input.getInstance().getProcess(processName);
data.setProcessMetaData(processMetaData);
data.setDefaultValues(new HashMap<>(input.getQueryParams()));
}
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.model.actions.widgets.RenderWidgetInput;
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.metadata.dashboard.QuickSightChartMetaData;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
@ -74,8 +74,8 @@ public class QuickSightChartRenderer extends AbstractWidgetRenderer
final GenerateEmbedUrlForRegisteredUserResponse generateEmbedUrlForRegisteredUserResponse = quickSightClient.generateEmbedUrlForRegisteredUser(generateEmbedUrlForRegisteredUserRequest);
String embedUrl = generateEmbedUrlForRegisteredUserResponse.embedUrl();
QWidget widget = new QuickSightChart(input.getWidgetMetaData().getName(), quickSightMetaData.getLabel(), embedUrl);
String embedUrl = generateEmbedUrlForRegisteredUserResponse.embedUrl();
QWidgetData widget = new QuickSightChart(input.getWidgetMetaData().getName(), quickSightMetaData.getLabel(), embedUrl);
return (new RenderWidgetOutput(widget));
}
catch(Exception e)

View File

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

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget
**
*******************************************************************************/
public class ChartData implements QWidget
public class ChartData extends QWidgetData
{
/*
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
**
*******************************************************************************/
public class ChildRecordListData implements QWidget
public class ChildRecordListData extends QWidgetData
{
private String title;
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
**
*******************************************************************************/
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
**
*******************************************************************************/
public class FieldValueListData implements QWidget
public class FieldValueListData extends QWidgetData
{
private List<QFieldMetaData> fields;
private QRecord record;

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget
**
*******************************************************************************/
public class LineChartData implements QWidget
public class LineChartData extends QWidgetData
{
/*
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
**
*******************************************************************************/
public class LocationData implements QWidget
public class LocationData extends QWidgetData
{
private String imageUrl;
private String title;

View File

@ -29,7 +29,7 @@ import java.util.List;
** Model containing datastructure expected by frontend bar chart widget
**
*******************************************************************************/
public class MultiStatisticsData implements QWidget
public class MultiStatisticsData extends QWidgetData
{
private String title;
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.Map;
/*******************************************************************************
** 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 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
**
@ -201,38 +87,4 @@ public class ParentWidgetData implements QWidget
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
**
*******************************************************************************/
public class ProcessWidgetData implements QWidget
public class ProcessWidgetData extends QWidgetData
{
private QProcessMetaData processMetaData;
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
**
*******************************************************************************/
public class QuickSightChart implements QWidget
public class QuickSightChart extends QWidgetData
{
private String label;
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
**
*******************************************************************************/
public class RawHTML implements QWidget
public class RawHTML extends QWidgetData
{
private String title;
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
**
*******************************************************************************/
public class StatisticsData implements QWidget
public class StatisticsData extends QWidgetData
{
/*
interface BarChartData{

View File

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

View File

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

View File

@ -31,10 +31,9 @@ import java.util.List;
*******************************************************************************/
public class ParentWidgetMetaData extends QWidgetMetaData
{
private String title;
private List<String> childWidgetNameList;
private List<String> childProcessNameList;
private List<DropdownData> dropdowns;
private String title;
private List<String> childWidgetNameList;
private List<String> childProcessNameList;
@ -138,189 +137,4 @@ public class ParentWidgetMetaData extends QWidgetMetaData
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.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
@ -41,6 +43,7 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
protected Integer gridColumns;
protected QCodeReference codeReference;
private List<WidgetDropdownData> dropdowns;
protected Map<String, Serializable> defaultValues = new LinkedHashMap<>();
@ -299,4 +302,54 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
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.QWidgetMetaData;
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.modules.backend.implementations.memory.MemoryRecordStore;
import com.kingsrook.qqq.backend.core.utils.TestUtils;
@ -75,19 +76,19 @@ class ParentWidgetRendererTest
QWidgetMetaDataInterface parentWidget = new ParentWidgetMetaData()
.withTitle("Parent")
.withDropdowns(
List.of(
new ParentWidgetMetaData.DropdownData()
.withPossibleValueSourceName(TestUtils.defineStatesPossibleValueSource().getName()),
new ParentWidgetMetaData.DropdownData()
.withPossibleValueSourceName(TestUtils.defineShapePossibleValueSource().getName())
)
)
.withChildWidgetNameList(
List.of(
ProcessWidgetRenderer.class.getSimpleName()
)
)
.withDropdowns(
List.of(
new WidgetDropdownData()
.withPossibleValueSourceName(TestUtils.defineStatesPossibleValueSource().getName()),
new WidgetDropdownData()
.withPossibleValueSourceName(TestUtils.defineShapePossibleValueSource().getName())
)
)
.withType(WidgetType.PARENT_WIDGET.getType())
.withName(ProcessWidgetRenderer.class.getSimpleName())
.withGridColumns(12)