From 8454f940200b6e0d1c7f2a83f374b9e44af56dc6 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Thu, 8 Dec 2022 15:06:40 -0600 Subject: [PATCH] SPRINT-17: updated dropdowns to be required, added divider --- .../widgets/DividerWidgetRenderer.java | 47 ++++++++++++++++++ .../widgets/ParentWidgetRenderer.java | 37 ++++++++++++-- .../SearchPossibleValueSourceAction.java | 13 +++-- .../actions/widgets/RenderWidgetInput.java | 2 +- .../model/dashboard/widgets/ChartData.java | 47 +++++++----------- .../dashboard/widgets/DividerWidgetData.java | 48 +++++++++++++++++++ .../dashboard/widgets/ParentWidgetData.java | 37 +++++++++++++- .../model/dashboard/widgets/WidgetType.java | 1 + .../dashboard/ParentWidgetMetaData.java | 41 ++++++++++++++-- 9 files changed, 230 insertions(+), 43 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/DividerWidgetRenderer.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/DividerWidgetData.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/DividerWidgetRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/DividerWidgetRenderer.java new file mode 100644 index 00000000..4cc9a5f3 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/DividerWidgetRenderer.java @@ -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 . + */ + +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())); + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ParentWidgetRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ParentWidgetRenderer.java index bca03c6c..b3d134ac 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ParentWidgetRenderer.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ParentWidgetRenderer.java @@ -69,9 +69,10 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer ///////////////////////////////////////////////////////////// // handle any PVSs creating dropdown data for the frontend // ///////////////////////////////////////////////////////////// - List>> pvsData = new ArrayList<>(); - List pvsLabels = new ArrayList<>(); - List pvsNames = new ArrayList<>(); + List>> pvsData = new ArrayList<>(); + List pvsLabels = new ArrayList<>(); + List pvsNames = new ArrayList<>(); + List missingRequiredSelections = new ArrayList<>(); for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns())) { 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, // // 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); SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance()); @@ -126,12 +128,37 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer "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); - 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)); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/values/SearchPossibleValueSourceAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/values/SearchPossibleValueSourceAction.java index f6490000..369785ed 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/values/SearchPossibleValueSourceAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/values/SearchPossibleValueSourceAction.java @@ -161,7 +161,6 @@ public class SearchPossibleValueSourceAction QQueryFilter queryFilter = new QQueryFilter(); queryFilter.setBooleanOperator(QQueryFilter.BooleanOperator.OR); - queryInput.setFilter(queryFilter); if(input.getIdList() != null) { @@ -207,11 +206,19 @@ public class SearchPossibleValueSourceAction queryFilter.setOrderBys(possibleValueSource.getOrderByFields()); - // todo - default filter - // todo - skip & limit as params 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); List ids = queryOutput.getRecords().stream().map(r -> r.getValue(table.getPrimaryKeyField())).toList(); List> qPossibleValues = possibleValueTranslator.buildTranslatedPossibleValueList(possibleValueSource, ids); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/widgets/RenderWidgetInput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/widgets/RenderWidgetInput.java index a6a868e3..395c09f4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/widgets/RenderWidgetInput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/widgets/RenderWidgetInput.java @@ -38,7 +38,7 @@ public class RenderWidgetInput extends AbstractActionInput { private QSession session; private QWidgetMetaDataInterface widgetMetaData; - private Map queryParams; + private Map queryParams = new HashMap<>(); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ChartData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ChartData.java index d2ffc89c..6432d041 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ChartData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ChartData.java @@ -41,12 +41,11 @@ public class ChartData implements QWidget } */ - private String title; - private String description; - private List colors; - private Data chartData; - private boolean isCurrency = false; - private int height; + private String title; + private String description; + private Data chartData; + private boolean isCurrency = false; + private int height; @@ -68,9 +67,12 @@ public class ChartData implements QWidget setDescription(description); setChartData(new ChartData.Data() .withLabels(labels) - .withDatasets(new ChartData.Data.Dataset() - .withLabel(seriesLabel) - .withData(data))); + .withDatasets(List.of( + new ChartData.Data.Dataset() + .withLabel(seriesLabel) + .withData(data) + )) + ); } @@ -261,8 +263,8 @@ public class ChartData implements QWidget *******************************************************************************/ public static class Data { - private List labels; - private Dataset dataset; + private List labels; + private List datasets; @@ -306,22 +308,7 @@ public class ChartData implements QWidget *******************************************************************************/ public List getDatasets() { - if(dataset != null) - { - return List.of(dataset); - } - return List.of(); - } - - - - /******************************************************************************* - ** Setter for datasets - ** - *******************************************************************************/ - public void setDataset(Dataset dataset) - { - this.dataset = dataset; + return (datasets); } @@ -330,9 +317,9 @@ public class ChartData implements QWidget ** Fluent setter for datasets ** *******************************************************************************/ - public Data withDatasets(Dataset datasets) + public Data withDatasets(List datasets) { - this.dataset = datasets; + this.datasets = datasets; return (this); } @@ -344,8 +331,8 @@ public class ChartData implements QWidget public static class Dataset { private String label; - private String color; private List data; + private String color; diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/DividerWidgetData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/DividerWidgetData.java new file mode 100644 index 00000000..95e8295f --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/DividerWidgetData.java @@ -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 . + */ + +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(); + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ParentWidgetData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ParentWidgetData.java index 87dd5399..af6600cd 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ParentWidgetData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/ParentWidgetData.java @@ -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 @@ -43,6 +43,7 @@ public class ParentWidgetData implements QWidget private List>> dropdownDataList; private List childWidgetNameList; + private String dropdownNeedsSelectedText; @@ -200,4 +201,38 @@ 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); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/WidgetType.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/WidgetType.java index 00ccee71..ebe1fb96 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/WidgetType.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/WidgetType.java @@ -30,6 +30,7 @@ public enum WidgetType BAR_CHART("barChart"), CHART("chart"), CHILD_RECORD_LIST("childRecordList"), + DIVIDER("divider"), GENERIC("generic"), HORIZONTAL_BAR_CHART("horizontalBarChart"), HTML("html"), diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/ParentWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/ParentWidgetMetaData.java index 589cc570..c1f51123 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/ParentWidgetMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/ParentWidgetMetaData.java @@ -180,9 +180,10 @@ public class ParentWidgetMetaData extends QWidgetMetaData *******************************************************************************/ public static class DropdownData { - private String possibleValueSourceName; - private String foreignKeyFieldName; - private String label; + private String possibleValueSourceName; + private String foreignKeyFieldName; + private String label; + private boolean isRequired; @@ -286,6 +287,40 @@ public class ParentWidgetMetaData extends QWidgetMetaData 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); + } + } }