SPRINT-17: updates to parent widget dropdown data, updated group bys to be objects allowing group by with custom formats

This commit is contained in:
Tim Chamberlain
2022-12-07 15:31:48 -06:00
parent 241741e2e5
commit 9b34ee7fe7
14 changed files with 766 additions and 67 deletions

View File

@ -31,6 +31,9 @@ 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;
@ -40,6 +43,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaD
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;
/*******************************************************************************
@ -68,15 +72,42 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer
List<List<Map<String, String>>> pvsData = new ArrayList<>();
List<String> pvsLabels = new ArrayList<>();
List<String> pvsNames = new ArrayList<>();
for(String possibleValueSourceName : CollectionUtils.nonNullList(metaData.getPossibleValueNameList()))
for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
{
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
pvsLabels.add(possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName);
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 //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pvsLabels.add(dropdownData.getLabel() != null ? dropdownData.getLabel() : (possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName));
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<>();

View File

@ -38,7 +38,7 @@ public class AggregateInput extends AbstractTableActionInput
{
private QQueryFilter filter;
private List<Aggregate> aggregates;
private List<String> groupByFieldNames;
private List<GroupBy> groupBys = new ArrayList<>();
private List<QueryJoin> queryJoins = null;
@ -148,50 +148,50 @@ public class AggregateInput extends AbstractTableActionInput
/*******************************************************************************
** Getter for groupByFieldNames
** Getter for groupBys
**
*******************************************************************************/
public List<String> getGroupByFieldNames()
public List<GroupBy> getGroupBys()
{
return groupByFieldNames;
return groupBys;
}
/*******************************************************************************
** Setter for groupByFieldNames
** Setter for groupBys
**
*******************************************************************************/
public void setGroupByFieldNames(List<String> groupByFieldNames)
public void setGroupBys(List<GroupBy> groupBys)
{
this.groupByFieldNames = groupByFieldNames;
this.groupBys = groupBys;
}
/*******************************************************************************
** Fluent setter for groupByFieldNames
** Fluent setter for groupBys
**
*******************************************************************************/
public AggregateInput withGroupByFieldNames(List<String> groupByFieldNames)
public AggregateInput withGroupBys(List<GroupBy> groupBys)
{
this.groupByFieldNames = groupByFieldNames;
this.groupBys = groupBys;
return (this);
}
/*******************************************************************************
** Fluent setter for groupByFieldNames
** Fluent setter for groupBys
**
*******************************************************************************/
public AggregateInput withGroupByFieldName(String groupByFieldName)
public AggregateInput withGroupBy(GroupBy groupBy)
{
if(this.groupByFieldNames == null)
if(this.groupBys == null)
{
this.groupByFieldNames = new ArrayList<>();
this.groupBys = new ArrayList<>();
}
this.groupByFieldNames.add(groupByFieldName);
this.groupBys.add(groupBy);
return (this);
}

View File

@ -33,7 +33,7 @@ import java.util.Map;
public class AggregateResult
{
private Map<Aggregate, Serializable> aggregateValues = new LinkedHashMap<>();
private Map<String, Serializable> groupByValues = new LinkedHashMap<>();
private Map<GroupBy, Serializable> groupByValues = new LinkedHashMap<>();
@ -101,7 +101,7 @@ public class AggregateResult
** Getter for groupByValues
**
*******************************************************************************/
public Map<String, Serializable> getGroupByValues()
public Map<GroupBy, Serializable> getGroupByValues()
{
return groupByValues;
}
@ -112,7 +112,7 @@ public class AggregateResult
** Setter for groupByValues
**
*******************************************************************************/
public void setGroupByValues(Map<String, Serializable> groupByValues)
public void setGroupByValues(Map<GroupBy, Serializable> groupByValues)
{
this.groupByValues = groupByValues;
}
@ -123,7 +123,7 @@ public class AggregateResult
** Fluent setter for groupByValues
**
*******************************************************************************/
public AggregateResult withGroupByValues(Map<String, Serializable> groupByValues)
public AggregateResult withGroupByValues(Map<GroupBy, Serializable> groupByValues)
{
this.groupByValues = groupByValues;
return (this);
@ -135,13 +135,13 @@ public class AggregateResult
** Fluent setter for groupByValues
**
*******************************************************************************/
public AggregateResult withGroupByValue(String fieldName, Serializable value)
public AggregateResult withGroupByValue(GroupBy groupBy, Serializable value)
{
if(this.groupByValues == null)
{
this.groupByValues = new LinkedHashMap<>();
}
this.groupByValues.put(fieldName, value);
this.groupByValues.put(groupBy, value);
return (this);
}
@ -150,9 +150,9 @@ public class AggregateResult
/*******************************************************************************
**
*******************************************************************************/
public Serializable getGroupByValue(String fieldName)
public Serializable getGroupByValue(GroupBy groupBy)
{
return (this.groupByValues.get(fieldName));
return (this.groupByValues.get(groupBy));
}
}

View File

@ -0,0 +1,152 @@
/*
* 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.actions.tables.aggregate;
import java.io.Serializable;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
/*******************************************************************************
**
*******************************************************************************/
public class GroupBy implements Serializable
{
private QFieldType type;
private String fieldName;
private String formatString;
/*******************************************************************************
**
*******************************************************************************/
public GroupBy(QFieldType type, String fieldName, String formatString)
{
this.type = type;
this.fieldName = fieldName;
this.formatString = formatString;
}
/*******************************************************************************
** Getter for type
**
*******************************************************************************/
public QFieldType getType()
{
return type;
}
/*******************************************************************************
** Setter for type
**
*******************************************************************************/
public void setType(QFieldType type)
{
this.type = type;
}
/*******************************************************************************
** Fluent setter for type
**
*******************************************************************************/
public GroupBy withType(QFieldType type)
{
this.type = type;
return (this);
}
/*******************************************************************************
** Getter for fieldName
**
*******************************************************************************/
public String getFieldName()
{
return fieldName;
}
/*******************************************************************************
** Setter for fieldName
**
*******************************************************************************/
public void setFieldName(String fieldName)
{
this.fieldName = fieldName;
}
/*******************************************************************************
** Fluent setter for fieldName
**
*******************************************************************************/
public GroupBy withFieldName(String fieldName)
{
this.fieldName = fieldName;
return (this);
}
/*******************************************************************************
** Getter for formatString
**
*******************************************************************************/
public String getFormatString()
{
return formatString;
}
/*******************************************************************************
** Setter for formatString
**
*******************************************************************************/
public void setFormatString(String formatString)
{
this.formatString = formatString;
}
/*******************************************************************************
** Fluent setter for formatString
**
*******************************************************************************/
public GroupBy withFormatString(String formatString)
{
this.formatString = formatString;
return (this);
}
}

View File

@ -0,0 +1,123 @@
/*
* 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.actions.tables.aggregate;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
/*******************************************************************************
** Bean representing an element of a query order-by clause - ordering by a
** group by
**
*******************************************************************************/
public class QFilterOrderByGroupBy extends QFilterOrderBy implements Cloneable
{
private GroupBy groupBy;
/*******************************************************************************
**
*******************************************************************************/
@Override
public QFilterOrderByGroupBy clone()
{
return (QFilterOrderByGroupBy) super.clone();
}
/*******************************************************************************
** Default no-arg constructor
*******************************************************************************/
public QFilterOrderByGroupBy()
{
}
/*******************************************************************************
** Constructor that sets groupBy, but leaves default for isAscending (true)
*******************************************************************************/
public QFilterOrderByGroupBy(GroupBy groupBy)
{
this.groupBy = groupBy;
}
/*******************************************************************************
** Constructor that takes groupBy and isAscending.
*******************************************************************************/
public QFilterOrderByGroupBy(GroupBy groupBy, boolean isAscending)
{
this.groupBy = groupBy;
setIsAscending(isAscending);
}
/*******************************************************************************
** Getter for groupBy
**
*******************************************************************************/
public GroupBy getGroupBy()
{
return groupBy;
}
/*******************************************************************************
** Setter for groupBy
**
*******************************************************************************/
public void setGroupBy(GroupBy groupBy)
{
this.groupBy = groupBy;
}
/*******************************************************************************
** Fluent setter for groupBy
**
*******************************************************************************/
public QFilterOrderByGroupBy withGroupBy(GroupBy groupBy)
{
this.groupBy = groupBy;
return (this);
}
/*******************************************************************************
**
*******************************************************************************/
@Override
public String toString()
{
return (groupBy + " " + (getIsAscending() ? "ASC" : "DESC"));
}
}

View File

@ -41,9 +41,21 @@ public class ChartData implements QWidget
}
*/
private String title;
private String description;
private Data chartData;
private String title;
private String description;
private List<String> colors;
private Data chartData;
private boolean isCurrency = false;
private int height;
/*******************************************************************************
**
*******************************************************************************/
public ChartData()
{
}
@ -176,6 +188,74 @@ public class ChartData implements QWidget
/*******************************************************************************
** Getter for isCurrency
**
*******************************************************************************/
public boolean getIsCurrency()
{
return isCurrency;
}
/*******************************************************************************
** Setter for isCurrency
**
*******************************************************************************/
public void setIsCurrency(boolean isCurrency)
{
this.isCurrency = isCurrency;
}
/*******************************************************************************
** Fluent setter for isCurrency
**
*******************************************************************************/
public ChartData withIsCurrency(boolean isCurrency)
{
this.isCurrency = isCurrency;
return (this);
}
/*******************************************************************************
** Getter for height
**
*******************************************************************************/
public int getHeight()
{
return height;
}
/*******************************************************************************
** Setter for height
**
*******************************************************************************/
public void setHeight(int height)
{
this.height = height;
}
/*******************************************************************************
** Fluent setter for height
**
*******************************************************************************/
public ChartData withHeight(int height)
{
this.height = height;
return (this);
}
/*******************************************************************************
**
*******************************************************************************/
@ -224,9 +304,13 @@ public class ChartData implements QWidget
** Getter for datasets
**
*******************************************************************************/
public Dataset getDataset()
public List<Dataset> getDatasets()
{
return dataset;
if(dataset != null)
{
return List.of(dataset);
}
return List.of();
}
@ -260,6 +344,7 @@ public class ChartData implements QWidget
public static class Dataset
{
private String label;
private String color;
private List<Number> data;
@ -286,6 +371,40 @@ public class ChartData implements QWidget
/*******************************************************************************
** Getter for color
**
*******************************************************************************/
public String getColor()
{
return color;
}
/*******************************************************************************
** Setter for color
**
*******************************************************************************/
public void setColor(String color)
{
this.color = color;
}
/*******************************************************************************
** Fluent setter for color
**
*******************************************************************************/
public Dataset withColor(String color)
{
this.color = color;
return (this);
}
/*******************************************************************************
** Fluent setter for label
**

View File

@ -44,8 +44,9 @@ public class LineChartData implements QWidget
};
*/
private String title;
private Data chartData;
private String title;
private Data chartData;
private boolean isYAxisCurrency = false;
@ -151,6 +152,40 @@ public class LineChartData implements QWidget
/*******************************************************************************
** Getter for isYAxisCurrency
**
*******************************************************************************/
public boolean getIsYAxisCurrency()
{
return isYAxisCurrency;
}
/*******************************************************************************
** Setter for isYAxisCurrency
**
*******************************************************************************/
public void setIsYAxisCurrency(boolean isYAxisCurrency)
{
this.isYAxisCurrency = isYAxisCurrency;
}
/*******************************************************************************
** Fluent setter for isYAxisCurrency
**
*******************************************************************************/
public LineChartData withIsYAxisCurrency(boolean isYAxisCurrency)
{
this.isYAxisCurrency = isYAxisCurrency;
return (this);
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -38,17 +38,18 @@ public class StatisticsData implements QWidget
}
*/
private String title;
private int count;
private Number percentageAmount;
private String percentageLabel;
private String title;
private Number count;
private Number percentageAmount;
private String percentageLabel;
private boolean isCurrency = false;
/*******************************************************************************
**
*******************************************************************************/
public StatisticsData(String title, int count, Number percentageAmount, String percentageLabel)
public StatisticsData(String title, Number count, Number percentageAmount, String percentageLabel)
{
this.title = title;
this.count = count;
@ -107,7 +108,7 @@ public class StatisticsData implements QWidget
** Getter for count
**
*******************************************************************************/
public int getCount()
public Number getCount()
{
return count;
}
@ -118,7 +119,7 @@ public class StatisticsData implements QWidget
** Setter for count
**
*******************************************************************************/
public void setCount(int count)
public void setCount(Number count)
{
this.count = count;
}
@ -129,7 +130,7 @@ public class StatisticsData implements QWidget
** Fluent setter for count
**
*******************************************************************************/
public StatisticsData withCount(int count)
public StatisticsData withCount(Number count)
{
this.count = count;
return (this);
@ -203,4 +204,38 @@ public class StatisticsData implements QWidget
return (this);
}
/*******************************************************************************
** Getter for isCurrency
**
*******************************************************************************/
public boolean getIsCurrency()
{
return isCurrency;
}
/*******************************************************************************
** Setter for isCurrency
**
*******************************************************************************/
public void setIsCurrency(boolean isCurrency)
{
this.isCurrency = isCurrency;
}
/*******************************************************************************
** Fluent setter for isCurrency
**
*******************************************************************************/
public StatisticsData withIsCurrency(boolean isCurrency)
{
this.isCurrency = isCurrency;
return (this);
}
}

View File

@ -27,9 +27,11 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
*******************************************************************************/
public enum WidgetType
{
BAR_CHART("barChart"),
CHART("chart"),
CHILD_RECORD_LIST("childRecordList"),
GENERIC("generic"),
HORIZONTAL_BAR_CHART("horizontalBarChart"),
HTML("html"),
LINE_CHART("lineChart"),
LOCATION("location"),

View File

@ -31,10 +31,11 @@ import java.util.List;
*******************************************************************************/
public class ParentWidgetMetaData extends QWidgetMetaData implements QWidgetMetaDataInterface
{
private String title;
private List<String> possibleValueNameList;
private List<String> childWidgetNameList;
private List<String> childProcessNameList;
private String title;
private List<String> possibleValueNameList;
private List<String> childWidgetNameList;
private List<String> childProcessNameList;
private List<DropdownData> dropdowns;
@ -172,4 +173,154 @@ public class ParentWidgetMetaData extends QWidgetMetaData implements QWidgetMeta
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;
/*******************************************************************************
** 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);
}
}
}

View File

@ -197,6 +197,23 @@ public class GeneralProcessUtils
/*******************************************************************************
** Query to get one entity by a unique key value. That field can be the primary
** key, or any other field on the table. Note, if multiple rows do match the value,
** only 1 (determined in an unspecified way) is returned.
*******************************************************************************/
public static <T extends QRecordEntity> Optional<T> getEntityByField(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue, Class<T> entityClass) throws QException
{
Optional<QRecord> optionalQRecord = getRecordByField(parentActionInput, tableName, fieldName, fieldValue);
if(optionalQRecord.isPresent())
{
return (Optional.of(QRecordEntity.fromQRecord(entityClass, optionalQRecord.get())));
}
return (Optional.empty());
}
/*******************************************************************************
** Query to get one record by a unique key value.
*******************************************************************************/