mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
SPRINT-17: updated dropdowns to be required, added divider
This commit is contained in:
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.actions.dashboard.widgets;
|
||||||
|
|
||||||
|
|
||||||
|
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.DividerWidgetData;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Generic widget for showing a divider
|
||||||
|
*******************************************************************************/
|
||||||
|
public class DividerWidgetRenderer extends AbstractWidgetRenderer
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
||||||
|
{
|
||||||
|
ActionHelper.validateSession(input);
|
||||||
|
return (new RenderWidgetOutput(new DividerWidgetData()));
|
||||||
|
}
|
||||||
|
}
|
@ -69,9 +69,10 @@ 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<>();
|
List<List<Map<String, String>>> pvsData = new ArrayList<>();
|
||||||
List<String> pvsLabels = new ArrayList<>();
|
List<String> pvsLabels = new ArrayList<>();
|
||||||
List<String> pvsNames = new ArrayList<>();
|
List<String> pvsNames = new ArrayList<>();
|
||||||
|
List<String> missingRequiredSelections = new ArrayList<>();
|
||||||
for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
|
for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
|
||||||
{
|
{
|
||||||
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
|
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
|
||||||
@ -81,7 +82,8 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer
|
|||||||
// this looks complicated, but is just look for a label in the dropdown data and if found use it, //
|
// 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 //
|
// 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));
|
String pvsLabel = dropdownData.getLabel() != null ? dropdownData.getLabel() : (possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName);
|
||||||
|
pvsLabels.add(pvsLabel);
|
||||||
pvsNames.add(possibleValueSourceName);
|
pvsNames.add(possibleValueSourceName);
|
||||||
|
|
||||||
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
|
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
|
||||||
@ -126,12 +128,37 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer
|
|||||||
"label", possibleValue.getLabel()
|
"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.setDropdownNameList(pvsNames);
|
||||||
widgetData.setDropdownLabelList(pvsLabels);
|
widgetData.setDropdownLabelList(pvsLabels);
|
||||||
widgetData.setDropdownDataList(pvsData);
|
widgetData.setDropdownDataList(pvsData);
|
||||||
widgetData.setChildWidgetNameList(metaData.getChildWidgetNameList());
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
|
||||||
return (new RenderWidgetOutput(widgetData));
|
return (new RenderWidgetOutput(widgetData));
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,6 @@ public class SearchPossibleValueSourceAction
|
|||||||
|
|
||||||
QQueryFilter queryFilter = new QQueryFilter();
|
QQueryFilter queryFilter = new QQueryFilter();
|
||||||
queryFilter.setBooleanOperator(QQueryFilter.BooleanOperator.OR);
|
queryFilter.setBooleanOperator(QQueryFilter.BooleanOperator.OR);
|
||||||
queryInput.setFilter(queryFilter);
|
|
||||||
|
|
||||||
if(input.getIdList() != null)
|
if(input.getIdList() != null)
|
||||||
{
|
{
|
||||||
@ -207,11 +206,19 @@ public class SearchPossibleValueSourceAction
|
|||||||
|
|
||||||
queryFilter.setOrderBys(possibleValueSource.getOrderByFields());
|
queryFilter.setOrderBys(possibleValueSource.getOrderByFields());
|
||||||
|
|
||||||
// todo - default filter
|
|
||||||
|
|
||||||
// todo - skip & limit as params
|
// todo - skip & limit as params
|
||||||
queryInput.setLimit(250);
|
queryInput.setLimit(250);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if given a default filter, make it the 'top level' filter and the one we just created a subfilter //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(input.getDefaultQueryFilter() != null)
|
||||||
|
{
|
||||||
|
input.getDefaultQueryFilter().addSubFilter(queryFilter);
|
||||||
|
queryFilter = input.getDefaultQueryFilter();
|
||||||
|
}
|
||||||
|
queryInput.setFilter(queryFilter);
|
||||||
|
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
List<Serializable> ids = queryOutput.getRecords().stream().map(r -> r.getValue(table.getPrimaryKeyField())).toList();
|
List<Serializable> ids = queryOutput.getRecords().stream().map(r -> r.getValue(table.getPrimaryKeyField())).toList();
|
||||||
List<QPossibleValue<?>> qPossibleValues = possibleValueTranslator.buildTranslatedPossibleValueList(possibleValueSource, ids);
|
List<QPossibleValue<?>> qPossibleValues = possibleValueTranslator.buildTranslatedPossibleValueList(possibleValueSource, ids);
|
||||||
|
@ -38,7 +38,7 @@ public class RenderWidgetInput extends AbstractActionInput
|
|||||||
{
|
{
|
||||||
private QSession session;
|
private QSession session;
|
||||||
private QWidgetMetaDataInterface widgetMetaData;
|
private QWidgetMetaDataInterface widgetMetaData;
|
||||||
private Map<String, String> queryParams;
|
private Map<String, String> queryParams = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,12 +41,11 @@ public class ChartData implements QWidget
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private String description;
|
private String description;
|
||||||
private List<String> colors;
|
private Data chartData;
|
||||||
private Data chartData;
|
private boolean isCurrency = false;
|
||||||
private boolean isCurrency = false;
|
private int height;
|
||||||
private int height;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -68,9 +67,12 @@ public class ChartData implements QWidget
|
|||||||
setDescription(description);
|
setDescription(description);
|
||||||
setChartData(new ChartData.Data()
|
setChartData(new ChartData.Data()
|
||||||
.withLabels(labels)
|
.withLabels(labels)
|
||||||
.withDatasets(new ChartData.Data.Dataset()
|
.withDatasets(List.of(
|
||||||
.withLabel(seriesLabel)
|
new ChartData.Data.Dataset()
|
||||||
.withData(data)));
|
.withLabel(seriesLabel)
|
||||||
|
.withData(data)
|
||||||
|
))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,8 +263,8 @@ public class ChartData implements QWidget
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static class Data
|
public static class Data
|
||||||
{
|
{
|
||||||
private List<String> labels;
|
private List<String> labels;
|
||||||
private Dataset dataset;
|
private List<Dataset> datasets;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -306,22 +308,7 @@ public class ChartData implements QWidget
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public List<Dataset> getDatasets()
|
public List<Dataset> getDatasets()
|
||||||
{
|
{
|
||||||
if(dataset != null)
|
return (datasets);
|
||||||
{
|
|
||||||
return List.of(dataset);
|
|
||||||
}
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Setter for datasets
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public void setDataset(Dataset dataset)
|
|
||||||
{
|
|
||||||
this.dataset = dataset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -330,9 +317,9 @@ public class ChartData implements QWidget
|
|||||||
** Fluent setter for datasets
|
** Fluent setter for datasets
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Data withDatasets(Dataset datasets)
|
public Data withDatasets(List<Dataset> datasets)
|
||||||
{
|
{
|
||||||
this.dataset = datasets;
|
this.datasets = datasets;
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +331,8 @@ public class ChartData implements QWidget
|
|||||||
public static class Dataset
|
public static class Dataset
|
||||||
{
|
{
|
||||||
private String label;
|
private String label;
|
||||||
private String color;
|
|
||||||
private List<Number> data;
|
private List<Number> data;
|
||||||
|
private String color;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Model containing datastructure expected by frontend divider widget
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class DividerWidgetData implements QWidget
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public DividerWidgetData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for type
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return WidgetType.DIVIDER.getType();
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Model containing datastructure expected by frontend stepper widget
|
** Model containing datastructure expected by frontend parent widget
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ParentWidgetData implements QWidget
|
public class ParentWidgetData implements QWidget
|
||||||
@ -43,6 +43,7 @@ public class ParentWidgetData implements QWidget
|
|||||||
private List<List<Map<String, String>>> dropdownDataList;
|
private List<List<Map<String, String>>> dropdownDataList;
|
||||||
|
|
||||||
private List<String> childWidgetNameList;
|
private List<String> childWidgetNameList;
|
||||||
|
private String dropdownNeedsSelectedText;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -200,4 +201,38 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ public enum WidgetType
|
|||||||
BAR_CHART("barChart"),
|
BAR_CHART("barChart"),
|
||||||
CHART("chart"),
|
CHART("chart"),
|
||||||
CHILD_RECORD_LIST("childRecordList"),
|
CHILD_RECORD_LIST("childRecordList"),
|
||||||
|
DIVIDER("divider"),
|
||||||
GENERIC("generic"),
|
GENERIC("generic"),
|
||||||
HORIZONTAL_BAR_CHART("horizontalBarChart"),
|
HORIZONTAL_BAR_CHART("horizontalBarChart"),
|
||||||
HTML("html"),
|
HTML("html"),
|
||||||
|
@ -180,9 +180,10 @@ public class ParentWidgetMetaData extends QWidgetMetaData
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static class DropdownData
|
public static class DropdownData
|
||||||
{
|
{
|
||||||
private String possibleValueSourceName;
|
private String possibleValueSourceName;
|
||||||
private String foreignKeyFieldName;
|
private String foreignKeyFieldName;
|
||||||
private String label;
|
private String label;
|
||||||
|
private boolean isRequired;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -286,6 +287,40 @@ public class ParentWidgetMetaData extends QWidgetMetaData
|
|||||||
return (this);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user