diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
index 624c22e3..b1f00190 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
@@ -37,6 +37,7 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
import com.kingsrook.qqq.backend.core.actions.metadata.JoinGraph;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptActionInterface;
@@ -52,6 +53,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QSupplementalInstanceMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
@@ -158,6 +160,7 @@ public class QInstanceValidator
validateProcesses(qInstance);
validateReports(qInstance);
validateApps(qInstance);
+ validateWidgets(qInstance);
validatePossibleValueSources(qInstance);
validateQueuesAndProviders(qInstance);
validateJoins(qInstance);
@@ -1546,12 +1549,53 @@ public class QInstanceValidator
}
}
}
+
+ //////////////////////
+ // validate widgets //
+ //////////////////////
+ for(String widgetName : CollectionUtils.nonNullList(app.getWidgets()))
+ {
+ assertCondition(qInstance.getWidget(widgetName) != null, "App " + appName + " widget " + widgetName + " is not a recognized widget.");
+ }
});
}
}
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private void validateWidgets(QInstance qInstance)
+ {
+ if(CollectionUtils.nullSafeHasContents(qInstance.getWidgets()))
+ {
+ qInstance.getWidgets().forEach((widgetName, widget) ->
+ {
+ assertCondition(Objects.equals(widgetName, widget.getName()), "Inconsistent naming for widget: " + widgetName + "/" + widget.getName() + ".");
+
+ if(assertCondition(widget.getCodeReference() != null, "Missing codeReference for widget: " + widgetName))
+ {
+ validateSimpleCodeReference("Widget " + widgetName + " code reference: ", widget.getCodeReference(), AbstractWidgetRenderer.class);
+ }
+
+ if(widget instanceof ParentWidgetMetaData parentWidgetMetaData)
+ {
+ if(assertCondition(CollectionUtils.nullSafeHasContents(parentWidgetMetaData.getChildWidgetNameList()), "Missing child widgets for parent widget: " + widget.getName()))
+ {
+ for(String childWidgetName : parentWidgetMetaData.getChildWidgetNameList())
+ {
+ assertCondition(qInstance.getWidget(childWidgetName) != null, "Unrecognized child widget name [" + childWidgetName + "] in parent widget: " + widget.getName());
+ }
+ }
+ }
+ }
+ );
+ }
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QQueryFilter.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QQueryFilter.java
index b4020027..3d07c4c2 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QQueryFilter.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QQueryFilter.java
@@ -372,7 +372,7 @@ public class QQueryFilter implements Serializable, Cloneable
rs.append(")");
rs.append("OrderBy[");
- for(QFilterOrderBy orderBy : orderBys)
+ for(QFilterOrderBy orderBy : CollectionUtils.nonNullList(orderBys))
{
rs.append(orderBy).append(",");
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/CompositeWidgetData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/CompositeWidgetData.java
new file mode 100644
index 00000000..4d2e79a7
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/CompositeWidgetData.java
@@ -0,0 +1,220 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseSlots;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseStyles;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseValues;
+
+
+/*******************************************************************************
+ ** Data used to render a Composite Widget - e.g., a collection of blocks
+ *******************************************************************************/
+public class CompositeWidgetData extends AbstractBlockWidgetData
+{
+ private List> blocks = new ArrayList<>();
+
+ private Map styleOverrides = new HashMap<>();
+
+ private Layout layout;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public enum Layout
+ {
+ /////////////////////////////////////////////////////////////
+ // note, these are used in QQQ FMD CompositeWidgetData.tsx //
+ /////////////////////////////////////////////////////////////
+ FLEX_ROW_WRAPPED,
+ FLEX_ROW_SPACE_BETWEEN,
+ TABLE_SUB_ROW_DETAILS,
+ BADGES_WRAPPER
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "COMPOSITE";
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for blocks
+ **
+ *******************************************************************************/
+ public List> getBlocks()
+ {
+ return blocks;
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for blocks
+ **
+ *******************************************************************************/
+ public void setBlocks(List> blocks)
+ {
+ this.blocks = blocks;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for blocks
+ **
+ *******************************************************************************/
+ public CompositeWidgetData withBlocks(List> blocks)
+ {
+ this.blocks = blocks;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public CompositeWidgetData withBlock(AbstractBlockWidgetData, ?, ?, ?> block)
+ {
+ addBlock(block);
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addBlock(AbstractBlockWidgetData, ?, ?, ?> block)
+ {
+ if(this.blocks == null)
+ {
+ this.blocks = new ArrayList<>();
+ }
+ this.blocks.add(block);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for styleOverrides
+ *******************************************************************************/
+ public Map getStyleOverrides()
+ {
+ return (this.styleOverrides);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for styleOverrides
+ *******************************************************************************/
+ public void setStyleOverrides(Map styleOverrides)
+ {
+ this.styleOverrides = styleOverrides;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for styleOverrides
+ *******************************************************************************/
+ public CompositeWidgetData withStyleOverrides(Map styleOverrides)
+ {
+ this.styleOverrides = styleOverrides;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public CompositeWidgetData withStyleOverride(String key, Serializable value)
+ {
+ addStyleOverride(key, value);
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addStyleOverride(String key, Serializable value)
+ {
+ if(this.styleOverrides == null)
+ {
+ this.styleOverrides = new HashMap<>();
+ }
+ this.styleOverrides.put(key, value);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for layout
+ *******************************************************************************/
+ public Layout getLayout()
+ {
+ return (this.layout);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for layout
+ *******************************************************************************/
+ public void setLayout(Layout layout)
+ {
+ this.layout = layout;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for layout
+ *******************************************************************************/
+ public CompositeWidgetData withLayout(Layout layout)
+ {
+ this.layout = layout;
+ return (this);
+ }
+
+}
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 87338413..b19d65cb 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
@@ -35,6 +35,8 @@ public class ParentWidgetData extends QWidgetData
private List childWidgetNameList;
private ParentWidgetMetaData.LayoutType layoutType = ParentWidgetMetaData.LayoutType.GRID;
+ private boolean isLabelPageTitle = false;
+
/*******************************************************************************
@@ -121,4 +123,34 @@ public class ParentWidgetData extends QWidgetData
}
+
+ /*******************************************************************************
+ ** Getter for isLabelPageTitle
+ *******************************************************************************/
+ public boolean getIsLabelPageTitle()
+ {
+ return (this.isLabelPageTitle);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for isLabelPageTitle
+ *******************************************************************************/
+ public void setIsLabelPageTitle(boolean isLabelPageTitle)
+ {
+ this.isLabelPageTitle = isLabelPageTitle;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for isLabelPageTitle
+ *******************************************************************************/
+ public ParentWidgetData withIsLabelPageTitle(boolean isLabelPageTitle)
+ {
+ this.isLabelPageTitle = isLabelPageTitle;
+ return (this);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidgetData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidgetData.java
index 467554b3..82ea6754 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidgetData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidgetData.java
@@ -22,6 +22,7 @@
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
+import java.io.Serializable;
import java.util.List;
import java.util.Map;
@@ -47,6 +48,7 @@ public abstract class QWidgetData
private List>> dropdownDataList;
private String dropdownNeedsSelectedText;
+ private List> csvData;
/*******************************************************************************
@@ -324,4 +326,34 @@ public abstract class QWidgetData
}
+
+ /*******************************************************************************
+ ** Getter for csvData
+ *******************************************************************************/
+ public List> getCsvData()
+ {
+ return (this.csvData);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for csvData
+ *******************************************************************************/
+ public void setCsvData(List> csvData)
+ {
+ this.csvData = csvData;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for csvData
+ *******************************************************************************/
+ public QWidgetData withCsvData(List> csvData)
+ {
+ this.csvData = csvData;
+ return (this);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/StatisticsData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/StatisticsData.java
index 13a47931..cbd80e47 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/StatisticsData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/StatisticsData.java
@@ -22,19 +22,24 @@
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
+import java.io.Serializable;
+
+
/*******************************************************************************
** Model containing datastructure expected by frontend statistics widget
**
*******************************************************************************/
public class StatisticsData extends QWidgetData
{
- private Number count;
- private String countFontSize;
- private String countURL;
- private Number percentageAmount;
- private String percentageLabel;
- private boolean isCurrency = false;
- private boolean increaseIsGood = true;
+ private Serializable count;
+ private String countFontSize;
+ private String countURL;
+ private String countContext;
+ private Number percentageAmount;
+ private String percentageLabel;
+ private String percentageURL;
+ private boolean isCurrency = false;
+ private boolean increaseIsGood = true;
@@ -50,7 +55,7 @@ public class StatisticsData extends QWidgetData
/*******************************************************************************
**
*******************************************************************************/
- public StatisticsData(Number count, Number percentageAmount, String percentageLabel)
+ public StatisticsData(Serializable count, Number percentageAmount, String percentageLabel)
{
this.count = count;
this.percentageLabel = percentageLabel;
@@ -142,7 +147,7 @@ public class StatisticsData extends QWidgetData
** Getter for count
**
*******************************************************************************/
- public Number getCount()
+ public Serializable getCount()
{
return count;
}
@@ -153,7 +158,7 @@ public class StatisticsData extends QWidgetData
** Setter for count
**
*******************************************************************************/
- public void setCount(Number count)
+ public void setCount(Serializable count)
{
this.count = count;
}
@@ -164,7 +169,7 @@ public class StatisticsData extends QWidgetData
** Fluent setter for count
**
*******************************************************************************/
- public StatisticsData withCount(Number count)
+ public StatisticsData withCount(Serializable count)
{
this.count = count;
return (this);
@@ -306,4 +311,66 @@ public class StatisticsData extends QWidgetData
return (this);
}
+
+
+ /*******************************************************************************
+ ** Getter for countContext
+ *******************************************************************************/
+ public String getCountContext()
+ {
+ return (this.countContext);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for countContext
+ *******************************************************************************/
+ public void setCountContext(String countContext)
+ {
+ this.countContext = countContext;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for countContext
+ *******************************************************************************/
+ public StatisticsData withCountContext(String countContext)
+ {
+ this.countContext = countContext;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for percentageURL
+ *******************************************************************************/
+ public String getPercentageURL()
+ {
+ return (this.percentageURL);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for percentageURL
+ *******************************************************************************/
+ public void setPercentageURL(String percentageURL)
+ {
+ this.percentageURL = percentageURL;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for percentageURL
+ *******************************************************************************/
+ public StatisticsData withPercentageURL(String percentageURL)
+ {
+ this.percentageURL = percentageURL;
+ 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 5ea38183..421164a5 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
@@ -48,6 +48,7 @@ public enum WidgetType
STEPPER("stepper"),
TABLE("table"),
USA_MAP("usaMap"),
+ COMPOSITE("composite"),
DATA_BAG_VIEWER("dataBagViewer"),
SCRIPT_VIEWER("scriptViewer");
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/AbstractBlockWidgetData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/AbstractBlockWidgetData.java
new file mode 100644
index 00000000..09c45faf
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/AbstractBlockWidgetData.java
@@ -0,0 +1,386 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidgetData;
+
+
+/*******************************************************************************
+ ** Base class for the data returned in rendering a block of a specific type.
+ **
+ ** The type parameters define the structure of the block's data, and should
+ ** generally be defined along with a sub-class of this class, in a block-specific
+ ** sub-package.
+ *******************************************************************************/
+public abstract class AbstractBlockWidgetData<
+ T extends AbstractBlockWidgetData,
+ V extends BlockValuesInterface,
+ S extends BlockSlotsInterface,
+ SX extends BlockStylesInterface> extends QWidgetData
+{
+ private BlockTooltip tooltip;
+ private BlockLink link;
+
+ private Map tooltipMap;
+ private Map linkMap;
+
+ private V values;
+ private SX styles;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public final String getType()
+ {
+ return "block";
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public abstract String getBlockTypeName();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public T withTooltip(S key, String value)
+ {
+ addTooltip(key, value);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addTooltip(S key, String value)
+ {
+ if(this.tooltipMap == null)
+ {
+ this.tooltipMap = new HashMap<>();
+ }
+ this.tooltipMap.put(key, new BlockTooltip().withTitle(value));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public T withTooltip(S key, BlockTooltip value)
+ {
+ addTooltip(key, value);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addTooltip(S key, BlockTooltip value)
+ {
+ if(this.tooltipMap == null)
+ {
+ this.tooltipMap = new HashMap<>();
+ }
+ this.tooltipMap.put(key, value);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for tooltipMap
+ *******************************************************************************/
+ public Map getTooltipMap()
+ {
+ return (this.tooltipMap);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for tooltipMap
+ *******************************************************************************/
+ public void setTooltipMap(Map tooltipMap)
+ {
+ this.tooltipMap = tooltipMap;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for tooltipMap
+ *******************************************************************************/
+ public T withTooltipMap(Map tooltipMap)
+ {
+ this.tooltipMap = tooltipMap;
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for tooltip
+ **
+ *******************************************************************************/
+ public BlockTooltip getTooltip()
+ {
+ return tooltip;
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for tooltip
+ **
+ *******************************************************************************/
+ public void setTooltip(BlockTooltip tooltip)
+ {
+ this.tooltip = tooltip;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for tooltip
+ **
+ *******************************************************************************/
+ public T withTooltip(String tooltip)
+ {
+ this.tooltip = new BlockTooltip(tooltip);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for tooltip
+ **
+ *******************************************************************************/
+ public T withTooltip(BlockTooltip tooltip)
+ {
+ this.tooltip = tooltip;
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public T withLink(S key, String value)
+ {
+ addLink(key, value);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addLink(S key, String value)
+ {
+ if(this.linkMap == null)
+ {
+ this.linkMap = new HashMap<>();
+ }
+ this.linkMap.put(key, new BlockLink(value));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public T withLink(S key, BlockLink value)
+ {
+ addLink(key, value);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void addLink(S key, BlockLink value)
+ {
+ if(this.linkMap == null)
+ {
+ this.linkMap = new HashMap<>();
+ }
+ this.linkMap.put(key, value);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for linkMap
+ *******************************************************************************/
+ public Map getLinkMap()
+ {
+ return (this.linkMap);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for linkMap
+ *******************************************************************************/
+ public void setLinkMap(Map linkMap)
+ {
+ this.linkMap = linkMap;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for linkMap
+ *******************************************************************************/
+ public T withLinkMap(Map linkMap)
+ {
+ this.linkMap = linkMap;
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for link
+ **
+ *******************************************************************************/
+ public BlockLink getLink()
+ {
+ return link;
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for link
+ **
+ *******************************************************************************/
+ public void setLink(BlockLink link)
+ {
+ this.link = link;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for link
+ **
+ *******************************************************************************/
+ public T withLink(String link)
+ {
+ this.link = new BlockLink(link);
+ return (T) (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for link
+ **
+ *******************************************************************************/
+ public T withLink(BlockLink link)
+ {
+ this.link = link;
+ return (T) this;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for values
+ *******************************************************************************/
+ public V getValues()
+ {
+ return (this.values);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for values
+ *******************************************************************************/
+ public void setValues(V values)
+ {
+ this.values = values;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for values
+ *******************************************************************************/
+ public T withValues(V values)
+ {
+ this.values = values;
+ return (T) this;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for styles
+ *******************************************************************************/
+ public SX getStyles()
+ {
+ return (this.styles);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for styles
+ *******************************************************************************/
+ public void setStyles(SX styles)
+ {
+ this.styles = styles;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for styles
+ *******************************************************************************/
+ public T withStyles(SX styles)
+ {
+ this.styles = styles;
+ return (T) this;
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockLink.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockLink.java
new file mode 100644
index 00000000..680daf59
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockLink.java
@@ -0,0 +1,86 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+/*******************************************************************************
+ ** A link used within a (widget) block.
+ **
+ ** Right now, just a href - but target is an obvious next-thing to add here.
+ *******************************************************************************/
+public class BlockLink
+{
+ private String href;
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public BlockLink()
+ {
+ }
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public BlockLink(String href)
+ {
+ this.href = href;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for href
+ *******************************************************************************/
+ public String getHref()
+ {
+ return (this.href);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for href
+ *******************************************************************************/
+ public void setHref(String href)
+ {
+ this.href = href;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for href
+ *******************************************************************************/
+ public BlockLink withHref(String href)
+ {
+ this.href = href;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockSlotsInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockSlotsInterface.java
new file mode 100644
index 00000000..eb345d6b
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockSlotsInterface.java
@@ -0,0 +1,32 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+/*******************************************************************************
+ ** marker-interface for classes (enums, actually) used to define the "slots"
+ ** within a widget-block that can have links or tooltips applied to them.
+ *******************************************************************************/
+public interface BlockSlotsInterface
+{
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockStylesInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockStylesInterface.java
new file mode 100644
index 00000000..3d646659
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockStylesInterface.java
@@ -0,0 +1,32 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+/*******************************************************************************
+ ** Marker interface for classes that define the "styles" that can be customized
+ ** within a particular widget-block type.
+ *******************************************************************************/
+public interface BlockStylesInterface
+{
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockTooltip.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockTooltip.java
new file mode 100644
index 00000000..0f33376c
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockTooltip.java
@@ -0,0 +1,122 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+/*******************************************************************************
+ ** A tooltip used within a (widget) block.
+ **
+ *******************************************************************************/
+public class BlockTooltip
+{
+ private String title;
+ private Placement placement = Placement.BOTTOM;
+
+
+
+ public enum Placement
+ {BOTTOM, LEFT, RIGHT, TOP}
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public BlockTooltip()
+ {
+ }
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public BlockTooltip(String title)
+ {
+ this.title = title;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for title
+ *******************************************************************************/
+ public String getTitle()
+ {
+ return (this.title);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for title
+ *******************************************************************************/
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for title
+ *******************************************************************************/
+ public BlockTooltip withTitle(String title)
+ {
+ this.title = title;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for placement
+ *******************************************************************************/
+ public Placement getPlacement()
+ {
+ return (this.placement);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for placement
+ *******************************************************************************/
+ public void setPlacement(Placement placement)
+ {
+ this.placement = placement;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for placement
+ *******************************************************************************/
+ public BlockTooltip withPlacement(Placement placement)
+ {
+ this.placement = placement;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockValuesInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockValuesInterface.java
new file mode 100644
index 00000000..a12c64a5
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/BlockValuesInterface.java
@@ -0,0 +1,32 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks;
+
+
+/*******************************************************************************
+ ** Marker interface for classes that define the values that can be returned for
+ ** a particular widget-block type.
+ *******************************************************************************/
+public interface BlockValuesInterface
+{
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseSlots.java
new file mode 100644
index 00000000..bd693990
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseSlots.java
@@ -0,0 +1,33 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.base;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum BaseSlots implements BlockSlotsInterface
+{
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseStyles.java
new file mode 100644
index 00000000..1aab7064
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseStyles.java
@@ -0,0 +1,33 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.base;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class BaseStyles implements BlockStylesInterface
+{
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseValues.java
new file mode 100644
index 00000000..a3bf9d61
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/base/BaseValues.java
@@ -0,0 +1,33 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.base;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class BaseValues implements BlockValuesInterface
+{
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberBlockData.java
new file mode 100644
index 00000000..adf2b0cb
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.bignumberblock;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class BigNumberBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "BIG_NUMBER";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberSlots.java
new file mode 100644
index 00000000..a442c5ca
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberSlots.java
@@ -0,0 +1,36 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.bignumberblock;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum BigNumberSlots implements BlockSlotsInterface
+{
+ HEADING,
+ NUMBER,
+ CONTEXT
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberStyles.java
new file mode 100644
index 00000000..ecbd442e
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberStyles.java
@@ -0,0 +1,98 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.bignumberblock;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class BigNumberStyles implements BlockStylesInterface
+{
+ private String numberColor;
+ private String width;
+
+
+
+ /*******************************************************************************
+ ** Getter for numberColor
+ *******************************************************************************/
+ public String getNumberColor()
+ {
+ return (this.numberColor);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for numberColor
+ *******************************************************************************/
+ public void setNumberColor(String numberColor)
+ {
+ this.numberColor = numberColor;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for numberColor
+ *******************************************************************************/
+ public BigNumberStyles withNumberColor(String numberColor)
+ {
+ this.numberColor = numberColor;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for width
+ *******************************************************************************/
+ public String getWidth()
+ {
+ return (this.width);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for width
+ *******************************************************************************/
+ public void setWidth(String width)
+ {
+ this.width = width;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for width
+ *******************************************************************************/
+ public BigNumberStyles withWidth(String width)
+ {
+ this.width = width;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberValues.java
new file mode 100644
index 00000000..e02df3aa
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/bignumberblock/BigNumberValues.java
@@ -0,0 +1,131 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.bignumberblock;
+
+
+import java.io.Serializable;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class BigNumberValues implements BlockValuesInterface
+{
+ private String heading;
+ private Serializable number;
+ private String context;
+
+
+
+ /*******************************************************************************
+ ** Getter for heading
+ *******************************************************************************/
+ public String getHeading()
+ {
+ return (this.heading);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for heading
+ *******************************************************************************/
+ public void setHeading(String heading)
+ {
+ this.heading = heading;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for heading
+ *******************************************************************************/
+ public BigNumberValues withHeading(String heading)
+ {
+ this.heading = heading;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for number
+ *******************************************************************************/
+ public Serializable getNumber()
+ {
+ return (this.number);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for number
+ *******************************************************************************/
+ public void setNumber(Serializable number)
+ {
+ this.number = number;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for number
+ *******************************************************************************/
+ public BigNumberValues withNumber(Serializable number)
+ {
+ this.number = number;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for context
+ *******************************************************************************/
+ public String getContext()
+ {
+ return (this.context);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for context
+ *******************************************************************************/
+ public void setContext(String context)
+ {
+ this.context = context;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for context
+ *******************************************************************************/
+ public BigNumberValues withContext(String context)
+ {
+ this.context = context;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/divider/DividerBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/divider/DividerBlockData.java
new file mode 100644
index 00000000..35daffbc
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/divider/DividerBlockData.java
@@ -0,0 +1,46 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.divider;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseSlots;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseStyles;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.base.BaseValues;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class DividerBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "DIVIDER";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeBlockData.java
new file mode 100644
index 00000000..5ad48f03
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.numbericonbadge;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class NumberIconBadgeBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "NUMBER_ICON_BADGE";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeSlots.java
new file mode 100644
index 00000000..f4adade3
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeSlots.java
@@ -0,0 +1,35 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.numbericonbadge;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum NumberIconBadgeSlots implements BlockSlotsInterface
+{
+ NUMBER,
+ ICON
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeStyles.java
new file mode 100644
index 00000000..a3df034f
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeStyles.java
@@ -0,0 +1,66 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.numbericonbadge;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class NumberIconBadgeStyles implements BlockStylesInterface
+{
+ private String color;
+
+
+
+ /*******************************************************************************
+ ** Getter for color
+ *******************************************************************************/
+ public String getColor()
+ {
+ return (this.color);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for color
+ *******************************************************************************/
+ public void setColor(String color)
+ {
+ this.color = color;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for color
+ *******************************************************************************/
+ public NumberIconBadgeStyles withColor(String color)
+ {
+ this.color = color;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeValues.java
new file mode 100644
index 00000000..7cb3b690
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/numbericonbadge/NumberIconBadgeValues.java
@@ -0,0 +1,99 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.numbericonbadge;
+
+
+import java.io.Serializable;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class NumberIconBadgeValues implements BlockValuesInterface
+{
+ private Serializable number;
+ private String iconName;
+
+
+
+ /*******************************************************************************
+ ** Getter for number
+ *******************************************************************************/
+ public Serializable getNumber()
+ {
+ return (this.number);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for number
+ *******************************************************************************/
+ public void setNumber(Serializable number)
+ {
+ this.number = number;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for number
+ *******************************************************************************/
+ public NumberIconBadgeValues withNumber(Serializable number)
+ {
+ this.number = number;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for iconName
+ *******************************************************************************/
+ public String getIconName()
+ {
+ return (this.iconName);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for iconName
+ *******************************************************************************/
+ public void setIconName(String iconName)
+ {
+ this.iconName = iconName;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for iconName
+ *******************************************************************************/
+ public NumberIconBadgeValues withIconName(String iconName)
+ {
+ this.iconName = iconName;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarBlockData.java
new file mode 100644
index 00000000..ddf11a88
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.progressbar;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class ProgressBarBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "PROGRESS_BAR";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarSlots.java
new file mode 100644
index 00000000..4882b90c
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarSlots.java
@@ -0,0 +1,36 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.progressbar;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum ProgressBarSlots implements BlockSlotsInterface
+{
+ HEADING,
+ BAR,
+ VALUE
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarStyles.java
new file mode 100644
index 00000000..9bcdb79d
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarStyles.java
@@ -0,0 +1,69 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.progressbar;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class ProgressBarStyles implements BlockStylesInterface
+{
+ private String barColor;
+
+
+
+ /*******************************************************************************
+ ** Getter for barColor
+ **
+ *******************************************************************************/
+ public String getBarColor()
+ {
+ return barColor;
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for barColor
+ **
+ *******************************************************************************/
+ public void setBarColor(String barColor)
+ {
+ this.barColor = barColor;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for barColor
+ **
+ *******************************************************************************/
+ public ProgressBarStyles withBarColor(String barColor)
+ {
+ this.barColor = barColor;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarValues.java
new file mode 100644
index 00000000..d5973eba
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/progressbar/ProgressBarValues.java
@@ -0,0 +1,131 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.progressbar;
+
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class ProgressBarValues implements BlockValuesInterface
+{
+ private String heading;
+ private BigDecimal percent;
+ private Serializable value;
+
+
+
+ /*******************************************************************************
+ ** Getter for heading
+ *******************************************************************************/
+ public String getHeading()
+ {
+ return (this.heading);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for heading
+ *******************************************************************************/
+ public void setHeading(String heading)
+ {
+ this.heading = heading;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for heading
+ *******************************************************************************/
+ public ProgressBarValues withHeading(String heading)
+ {
+ this.heading = heading;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for percent
+ *******************************************************************************/
+ public BigDecimal getPercent()
+ {
+ return (this.percent);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for percent
+ *******************************************************************************/
+ public void setPercent(BigDecimal percent)
+ {
+ this.percent = percent;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for percent
+ *******************************************************************************/
+ public ProgressBarValues withPercent(BigDecimal percent)
+ {
+ this.percent = percent;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for value
+ *******************************************************************************/
+ public Serializable getValue()
+ {
+ return (this.value);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for value
+ *******************************************************************************/
+ public void setValue(Serializable value)
+ {
+ this.value = value;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for value
+ *******************************************************************************/
+ public ProgressBarValues withValue(Serializable value)
+ {
+ this.value = value;
+ return (this);
+ }
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowBlockData.java
new file mode 100644
index 00000000..b222a7e3
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.tablesubrowdetailrow;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TableSubRowDetailRowBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "TABLE_SUB_ROW_DETAIL_ROW";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowSlots.java
new file mode 100644
index 00000000..01061676
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowSlots.java
@@ -0,0 +1,35 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.tablesubrowdetailrow;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum TableSubRowDetailRowSlots implements BlockSlotsInterface
+{
+ LABEL,
+ VALUE
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowStyles.java
new file mode 100644
index 00000000..183a647b
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowStyles.java
@@ -0,0 +1,98 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.tablesubrowdetailrow;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TableSubRowDetailRowStyles implements BlockStylesInterface
+{
+ private String labelColor;
+ private String valueColor;
+
+
+
+ /*******************************************************************************
+ ** Getter for labelColor
+ *******************************************************************************/
+ public String getLabelColor()
+ {
+ return (this.labelColor);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for labelColor
+ *******************************************************************************/
+ public void setLabelColor(String labelColor)
+ {
+ this.labelColor = labelColor;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for labelColor
+ *******************************************************************************/
+ public TableSubRowDetailRowStyles withLabelColor(String labelColor)
+ {
+ this.labelColor = labelColor;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for valueColor
+ *******************************************************************************/
+ public String getValueColor()
+ {
+ return (this.valueColor);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for valueColor
+ *******************************************************************************/
+ public void setValueColor(String valueColor)
+ {
+ this.valueColor = valueColor;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for valueColor
+ *******************************************************************************/
+ public TableSubRowDetailRowStyles withValueColor(String valueColor)
+ {
+ this.valueColor = valueColor;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowValues.java
new file mode 100644
index 00000000..148588c8
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/tablesubrowdetailrow/TableSubRowDetailRowValues.java
@@ -0,0 +1,121 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.tablesubrowdetailrow;
+
+
+import java.io.Serializable;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TableSubRowDetailRowValues implements BlockValuesInterface
+{
+ private String label;
+ private Serializable value;
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public TableSubRowDetailRowValues()
+ {
+ }
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public TableSubRowDetailRowValues(String label, Serializable value)
+ {
+ this.label = label;
+ this.value = value;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for label
+ *******************************************************************************/
+ public String getLabel()
+ {
+ return (this.label);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for label
+ *******************************************************************************/
+ public void setLabel(String label)
+ {
+ this.label = label;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for label
+ *******************************************************************************/
+ public TableSubRowDetailRowValues withLabel(String label)
+ {
+ this.label = label;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for value
+ *******************************************************************************/
+ public Serializable getValue()
+ {
+ return (this.value);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for value
+ *******************************************************************************/
+ public void setValue(Serializable value)
+ {
+ this.value = value;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for value
+ *******************************************************************************/
+ public TableSubRowDetailRowValues withValue(Serializable value)
+ {
+ this.value = value;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextBlockData.java
new file mode 100644
index 00000000..67764ec6
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.text;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TextBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "TEXT";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextSlots.java
new file mode 100644
index 00000000..753c37d1
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextSlots.java
@@ -0,0 +1,33 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.text;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum TextSlots implements BlockSlotsInterface
+{
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextStyles.java
new file mode 100644
index 00000000..f735798d
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextStyles.java
@@ -0,0 +1,33 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.text;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TextStyles implements BlockStylesInterface
+{
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextValues.java
new file mode 100644
index 00000000..3b82f4cb
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/text/TextValues.java
@@ -0,0 +1,87 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.text;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TextValues implements BlockValuesInterface
+{
+ private String text;
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public TextValues()
+ {
+ }
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public TextValues(String text)
+ {
+ setText(text);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for text
+ *******************************************************************************/
+ public String getText()
+ {
+ return (this.text);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for text
+ *******************************************************************************/
+ public void setText(String text)
+ {
+ this.text = text;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for text
+ *******************************************************************************/
+ public TextValues withText(String text)
+ {
+ this.text = text;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberBlockData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberBlockData.java
new file mode 100644
index 00000000..4d5daaad
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberBlockData.java
@@ -0,0 +1,43 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.upordownnumber;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.AbstractBlockWidgetData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class UpOrDownNumberBlockData extends AbstractBlockWidgetData
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getBlockTypeName()
+ {
+ return "UP_OR_DOWN_NUMBER";
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberSlots.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberSlots.java
new file mode 100644
index 00000000..d4240e07
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberSlots.java
@@ -0,0 +1,35 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.upordownnumber;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockSlotsInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum UpOrDownNumberSlots implements BlockSlotsInterface
+{
+ NUMBER,
+ CONTEXT
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberStyles.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberStyles.java
new file mode 100644
index 00000000..b3ac5e0d
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberStyles.java
@@ -0,0 +1,98 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.upordownnumber;
+
+
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockStylesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class UpOrDownNumberStyles implements BlockStylesInterface
+{
+ private String colorOverride;
+ private boolean isStacked = false;
+
+
+
+ /*******************************************************************************
+ ** Getter for colorOverride
+ *******************************************************************************/
+ public String getColorOverride()
+ {
+ return (this.colorOverride);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for colorOverride
+ *******************************************************************************/
+ public void setColorOverride(String colorOverride)
+ {
+ this.colorOverride = colorOverride;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for colorOverride
+ *******************************************************************************/
+ public UpOrDownNumberStyles withColorOverride(String colorOverride)
+ {
+ this.colorOverride = colorOverride;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for isStacked
+ *******************************************************************************/
+ public boolean getIsStacked()
+ {
+ return (this.isStacked);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for isStacked
+ *******************************************************************************/
+ public void setIsStacked(boolean isStacked)
+ {
+ this.isStacked = isStacked;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for isStacked
+ *******************************************************************************/
+ public UpOrDownNumberStyles withIsStacked(boolean isStacked)
+ {
+ this.isStacked = isStacked;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberValues.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberValues.java
new file mode 100644
index 00000000..937235d7
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/blocks/upordownnumber/UpOrDownNumberValues.java
@@ -0,0 +1,163 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.blocks.upordownnumber;
+
+
+import java.io.Serializable;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.BlockValuesInterface;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class UpOrDownNumberValues implements BlockValuesInterface
+{
+ private boolean isUp = false;
+ private boolean isGood = false;
+ private Serializable number;
+ private String context;
+
+
+
+ /*******************************************************************************
+ ** Getter for isUp
+ *******************************************************************************/
+ public boolean getIsUp()
+ {
+ return (this.isUp);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for isUp
+ *******************************************************************************/
+ public void setIsUp(boolean isUp)
+ {
+ this.isUp = isUp;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for isUp
+ *******************************************************************************/
+ public UpOrDownNumberValues withIsUp(boolean isUp)
+ {
+ this.isUp = isUp;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for isGood
+ *******************************************************************************/
+ public boolean getIsGood()
+ {
+ return (this.isGood);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for isGood
+ *******************************************************************************/
+ public void setIsGood(boolean isGood)
+ {
+ this.isGood = isGood;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for isGood
+ *******************************************************************************/
+ public UpOrDownNumberValues withIsGood(boolean isGood)
+ {
+ this.isGood = isGood;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for number
+ *******************************************************************************/
+ public Serializable getNumber()
+ {
+ return (this.number);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for number
+ *******************************************************************************/
+ public void setNumber(Serializable number)
+ {
+ this.number = number;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for number
+ *******************************************************************************/
+ public UpOrDownNumberValues withNumber(Serializable number)
+ {
+ this.number = number;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for context
+ *******************************************************************************/
+ public String getContext()
+ {
+ return (this.context);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for context
+ *******************************************************************************/
+ public void setContext(String context)
+ {
+ this.context = context;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for context
+ *******************************************************************************/
+ public UpOrDownNumberValues withContext(String context)
+ {
+ this.context = context;
+ return (this);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
index 977a552b..b6ea0975 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.google.common.reflect.ClassPath;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
@@ -50,13 +51,22 @@ public class MetaDataProducerHelper
**
** Note - they'll be sorted by the sortOrder they provide.
*******************************************************************************/
- public static void processAllMetaDataProducersInPackage(QInstance instance, String packageName) throws IOException
+ public static void processAllMetaDataProducersInPackage(QInstance instance, String packageName) throws QException
{
- ////////////////////////////////////////////////////////////////////////
- // find all the meta data producer classes in (and under) the package //
- ////////////////////////////////////////////////////////////////////////
- List> classesInPackage = getClassesInPackage(packageName);
- List> producers = new ArrayList<>();
+ List> classesInPackage;
+ try
+ {
+ ////////////////////////////////////////////////////////////////////////
+ // find all the meta data producer classes in (and under) the package //
+ ////////////////////////////////////////////////////////////////////////
+ classesInPackage = getClassesInPackage(packageName);
+ }
+ catch(Exception e)
+ {
+ throw (new QException("Error getting classes in package [" + packageName + "]", e));
+ }
+ List> producers = new ArrayList<>();
+
for(Class> aClass : classesInPackage)
{
try
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java
index c9453798..edab6c6e 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules;
@@ -55,7 +56,7 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
private boolean storeDropdownSelections;
private boolean showReloadButton = true;
- private boolean showExportButton = true;
+ private boolean showExportButton = false;
protected Map icons;
@@ -217,6 +218,17 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
public void setType(String type)
{
this.type = type;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // originally, showExportButton defaulted to true, and only a few frontend components knew how to render it. //
+ // but, with the advent of csvData that any widget type can export, then the generic frontend widget code //
+ // became aware of the export button, so we wanted to flip the default for showExportButton to false, but //
+ // still have it by-default be true for these 2 types //
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ if(WidgetType.TABLE.getType().equals(type) || WidgetType.CHILD_RECORD_LIST.getType().equals(type))
+ {
+ setShowExportButton(true);
+ }
}
@@ -227,7 +239,7 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
*******************************************************************************/
public QWidgetMetaData withType(String type)
{
- this.type = type;
+ setType(type);
return (this);
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java
index 3bf1f5a8..ef73eac8 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java
@@ -26,11 +26,13 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppSection;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QSupplementalAppMetaData;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@@ -51,6 +53,7 @@ public class QFrontendAppMetaData
private List sections;
+ private Map supplementalAppMetaData;
/*******************************************************************************
@@ -92,6 +95,31 @@ public class QFrontendAppMetaData
{
this.sections = filteredSections;
}
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // include supplemental meta data, based on if it's meant for full or partial frontend meta-data requests //
+ // todo - take includeFullMetaData as a param? //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ boolean includeFullMetaData = true;
+ for(QSupplementalAppMetaData supplementalAppMetaData : CollectionUtils.nonNullMap(appMetaData.getSupplementalMetaData()).values())
+ {
+ boolean include;
+ if(includeFullMetaData)
+ {
+ include = supplementalAppMetaData.includeInFullFrontendMetaData();
+ }
+ else
+ {
+ include = supplementalAppMetaData.includeInPartialFrontendMetaData();
+ }
+
+ if(include)
+ {
+ this.supplementalAppMetaData = Objects.requireNonNullElseGet(this.supplementalAppMetaData, HashMap::new);
+ this.supplementalAppMetaData.put(supplementalAppMetaData.getType(), supplementalAppMetaData);
+ }
+ }
+
}
@@ -196,4 +224,15 @@ public class QFrontendAppMetaData
{
return sections;
}
+
+
+
+ /*******************************************************************************
+ ** Getter for supplementalAppMetaData
+ **
+ *******************************************************************************/
+ public Map getSupplementalAppMetaData()
+ {
+ return supplementalAppMetaData;
+ }
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java
index 80725635..946fa448 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java
@@ -23,7 +23,9 @@ package com.kingsrook.qqq.backend.core.model.metadata.layout;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.TopLevelMetaDataInterface;
import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules;
@@ -55,6 +57,8 @@ public class QAppMetaData implements QAppChildMetaData, MetaDataWithPermissionRu
private List widgets;
private List sections;
+ private Map supplementalMetaData;
+
/*******************************************************************************
@@ -460,4 +464,50 @@ public class QAppMetaData implements QAppChildMetaData, MetaDataWithPermissionRu
return (this);
}
+
+
+ /*******************************************************************************
+ ** Getter for supplementalMetaData
+ *******************************************************************************/
+ public Map getSupplementalMetaData()
+ {
+ return (this.supplementalMetaData);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for supplementalMetaData
+ *******************************************************************************/
+ public void setSupplementalMetaData(Map supplementalMetaData)
+ {
+ this.supplementalMetaData = supplementalMetaData;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for supplementalMetaData
+ *******************************************************************************/
+ public QAppMetaData withSupplementalMetaData(QSupplementalAppMetaData supplementalMetaData)
+ {
+ if(this.supplementalMetaData == null)
+ {
+ this.supplementalMetaData = new HashMap<>();
+ }
+ this.supplementalMetaData.put(supplementalMetaData.getType(), supplementalMetaData);
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for supplementalMetaData
+ *******************************************************************************/
+ public QAppMetaData withSupplementalMetaData(Map supplementalMetaData)
+ {
+ this.supplementalMetaData = supplementalMetaData;
+ return (this);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QSupplementalAppMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QSupplementalAppMetaData.java
new file mode 100644
index 00000000..ab6f0a10
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QSupplementalAppMetaData.java
@@ -0,0 +1,86 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. 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.metadata.layout;
+
+
+import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ ** Base-class for app-level meta-data defined by some supplemental module, etc,
+ ** outside of qqq core
+ *******************************************************************************/
+public abstract class QSupplementalAppMetaData
+{
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public boolean includeInPartialFrontendMetaData()
+ {
+ return (false);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public boolean includeInFullFrontendMetaData()
+ {
+ return (false);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for type
+ *******************************************************************************/
+ public abstract String getType();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void enrich(QInstance qInstance, QTableMetaData table)
+ {
+ ////////////////////////
+ // noop in base class //
+ ////////////////////////
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void validate(QInstance qInstance, QTableMetaData tableMetaData, QInstanceValidator qInstanceValidator)
+ {
+ ////////////////////////
+ // noop in base class //
+ ////////////////////////
+ }
+}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/permissions/PermissionsHelperTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/permissions/PermissionsHelperTest.java
index 3ad4da49..cb61d4f7 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/permissions/PermissionsHelperTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/permissions/PermissionsHelperTest.java
@@ -25,13 +25,17 @@ package com.kingsrook.qqq.backend.core.actions.permissions;
import java.util.List;
import java.util.Set;
import com.kingsrook.qqq.backend.core.BaseTest;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessTest;
import com.kingsrook.qqq.backend.core.context.QContext;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QPermissionDeniedException;
import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
+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.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
@@ -541,13 +545,32 @@ class PermissionsHelperTest extends BaseTest
.withView(new QReportView().withType(ReportType.TABLE).withColumn(new QReportField("id"))));
qInstance.addWidget(new QWidgetMetaData()
- .withName(WIDGET_NAME));
+ .withName(WIDGET_NAME)
+ .withCodeReference(new QCodeReference(WidgetRenderer.class))
+ );
return (qInstance);
}
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class WidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ return null;
+ }
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
index f66dfa16..7cba47f0 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
@@ -31,6 +31,9 @@ import java.util.function.Function;
import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostQueryCustomizer;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
+import com.kingsrook.qqq.backend.core.actions.dashboard.PersonsByCreateDateBarChart;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.ParentWidgetRenderer;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException;
@@ -46,6 +49,7 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
@@ -803,7 +807,7 @@ class QInstanceValidatorTest extends BaseTest
**
*******************************************************************************/
@Test
- void testChildNotInAnySections()
+ void testAppChildNotInAnySections()
{
QTableMetaData table = new QTableMetaData().withName("test")
.withBackendName(TestUtils.DEFAULT_BACKEND_NAME)
@@ -822,6 +826,19 @@ class QInstanceValidatorTest extends BaseTest
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testAppUnrecognizedWidgetName()
+ {
+ QAppMetaData app = new QAppMetaData().withName("test")
+ .withWidgets(List.of("no-such-widget"));
+ assertValidationFailureReasons((qInstance) -> qInstance.addApp(app), "not a recognized widget");
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
@@ -1813,6 +1830,65 @@ class QInstanceValidatorTest extends BaseTest
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testWidgetNaming()
+ {
+ String name = PersonsByCreateDateBarChart.class.getSimpleName();
+
+ assertValidationFailureReasons((qInstance) -> qInstance.getWidget(name).withName(null),
+ "Inconsistent naming for widget");
+
+ assertValidationFailureReasons((qInstance) -> qInstance.getWidget(name).withName(""),
+ "Inconsistent naming for widget");
+
+ assertValidationFailureReasons((qInstance) -> qInstance.getWidget(name).withName("wrongName"),
+ "Inconsistent naming for widget");
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testWidgetCodeReference()
+ {
+ String name = PersonsByCreateDateBarChart.class.getSimpleName();
+
+ assertValidationFailureReasons((qInstance) -> qInstance.getWidget(name).withCodeReference(null),
+ "Missing codeReference for widget");
+
+ assertValidationFailureReasons((qInstance) -> qInstance.getWidget(name).withCodeReference(new QCodeReference(ArrayList.class)),
+ "CodeReference is not of the expected type: class " + AbstractWidgetRenderer.class.getName());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testParentWidgets()
+ {
+ assertValidationFailureReasons((qInstance) -> qInstance.addWidget(new ParentWidgetMetaData()
+ .withName("parentWidget")
+ .withCodeReference(new QCodeReference(ParentWidgetRenderer.class))
+ ),
+ "Missing child widgets");
+
+ assertValidationFailureReasons((qInstance) -> qInstance.addWidget(new ParentWidgetMetaData()
+ .withChildWidgetNameList(List.of("noSuchWidget"))
+ .withName("parentWidget")
+ .withCodeReference(new QCodeReference(ParentWidgetRenderer.class))
+ ),
+ "Unrecognized child widget name");
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
index ab1ae66f..84f70562 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
@@ -22,7 +22,7 @@
package com.kingsrook.qqq.backend.core.model.metadata;
-import java.io.IOException;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.metadata.producers.TestAbstractMetaDataProducer;
import com.kingsrook.qqq.backend.core.model.metadata.producers.TestDisabledMetaDataProducer;
import com.kingsrook.qqq.backend.core.model.metadata.producers.TestImplementsMetaDataProducer;
@@ -44,7 +44,7 @@ class MetaDataProducerHelperTest
**
*******************************************************************************/
@Test
- void test() throws IOException
+ void test() throws QException
{
QInstance qInstance = new QInstance();
MetaDataProducerHelper.processAllMetaDataProducersInPackage(qInstance, "com.kingsrook.qqq.backend.core.model.metadata.producers");
diff --git a/qqq-sample-project/pom.xml b/qqq-sample-project/pom.xml
index 5fdd4cd2..e41bd0ea 100644
--- a/qqq-sample-project/pom.xml
+++ b/qqq-sample-project/pom.xml
@@ -65,6 +65,11 @@
qqq-middleware-picocli
${revision}
+
+ com.kingsrook.qqq
+ qqq-frontend-material-dashboard
+ feature-CE-876-develop-missing-widget-types-20240221.011827-1
+
com.h2database
h2
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleCli.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleCli.java
index 78884a30..cd828001 100644
--- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleCli.java
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleCli.java
@@ -24,6 +24,7 @@ package com.kingsrook.sampleapp;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.frontend.picocli.QPicoCliImplementation;
+import com.kingsrook.sampleapp.metadata.SampleMetaDataProvider;
/*******************************************************************************
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java
index fdbc0249..7ec4a911 100644
--- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleJavalinServer.java
@@ -25,6 +25,7 @@ package com.kingsrook.sampleapp;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
+import com.kingsrook.sampleapp.metadata.SampleMetaDataProvider;
import io.javalin.Javalin;
import io.javalin.plugin.bundled.CorsPluginConfig;
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/SampleMetaDataProvider.java
similarity index 99%
rename from qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java
rename to qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/SampleMetaDataProvider.java
index af71a039..ec2aa618 100644
--- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/SampleMetaDataProvider.java
@@ -1,6 +1,6 @@
/*
* QQQ - Low-code Application Framework for Engineers.
- * Copyright (C) 2021-2022. Kingsrook, LLC
+ * Copyright (C) 2021-2024. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
@@ -19,7 +19,7 @@
* along with this program. If not, see .
*/
-package com.kingsrook.sampleapp;
+package com.kingsrook.sampleapp.metadata;
import java.io.Serializable;
@@ -35,6 +35,7 @@ import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
import com.kingsrook.qqq.backend.core.instances.QMetaDataVariableInterpreter;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerHelper;
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData;
@@ -127,6 +128,8 @@ public class SampleMetaDataProvider
qInstance.addProcess(defineProcessScreenThenSleep());
qInstance.addProcess(defineProcessSimpleThrow());
+ MetaDataProducerHelper.processAllMetaDataProducersInPackage(qInstance, SampleMetaDataProvider.class.getPackageName());
+
defineWidgets(qInstance);
defineBranding(qInstance);
defineApps(qInstance);
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBarChartWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBarChartWidgetMetaDataProducer.java
new file mode 100644
index 00000000..93f7f94a
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBarChartWidgetMetaDataProducer.java
@@ -0,0 +1,124 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.ChartData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleBarChart
+ *******************************************************************************/
+public class SampleBarChartWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleBarChartWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.BAR_CHART.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Bar Chart")
+ .withTooltip("This is a sample of a bar chart")
+ .withShowReloadButton(true)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_RIGHT_INSIDE_CARD, new QIcon("sports").withColor("#8F00D8"))
+ .withCodeReference(new QCodeReference(SampleBarChartRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleBarChartRenderer extends AbstractWidgetRenderer
+ {
+ private List labels = new ArrayList<>();
+ private List colors = new ArrayList<>();
+ private List data = new ArrayList<>();
+ private List urls = new ArrayList<>();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private void addSlice(String label, String color, Number datum, String url)
+ {
+ labels.add(label);
+ colors.add(color);
+ data.add(datum);
+ urls.add(url);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ addSlice("Apple", "#FF0000", 100, null);
+ addSlice("Orange", "#FF8000", 150, null);
+ addSlice("Banana", "#FFFF00", 75, null);
+ addSlice("Lime", "#00FF00", 100, null);
+ addSlice("Blueberry", "#0000FF", 200, null);
+
+ ChartData chartData = new ChartData()
+ .withChartData(new ChartData.Data()
+ .withLabels(labels)
+ .withDatasets(List.of(
+ new ChartData.Data.Dataset()
+ .withLabel("One")
+ .withData(data)
+ .withBackgroundColors(colors)
+ .withUrls(urls)
+ )));
+
+ chartData.setTitle("Bar Chart");
+
+ return (new RenderWidgetOutput(chartData));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBigNumberBlocksWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBigNumberBlocksWidgetMetaDataProducer.java
new file mode 100644
index 00000000..2907c722
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleBigNumberBlocksWidgetMetaDataProducer.java
@@ -0,0 +1,124 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.CompositeWidgetData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.bignumberblock.BigNumberBlockData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.bignumberblock.BigNumberStyles;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.bignumberblock.BigNumberValues;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.upordownnumber.UpOrDownNumberBlockData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.upordownnumber.UpOrDownNumberSlots;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.upordownnumber.UpOrDownNumberStyles;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks.upordownnumber.UpOrDownNumberValues;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleStatisticsWidget
+ *******************************************************************************/
+public class SampleBigNumberBlocksWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleBigNumberBlocksWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.COMPOSITE.getType())
+ .withGridColumns(12)
+ .withIsCard(true)
+ .withLabel("Big Number Blocks")
+ .withTooltip("This is a sample of a widget using Big Number Blocks")
+ .withShowReloadButton(false)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_LEFT_INSIDE_CARD, new QIcon("blocks").withColor("skyblue"))
+ .withCodeReference(new QCodeReference(SampleBigNumberBlocksWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleBigNumberBlocksWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ CompositeWidgetData data = new CompositeWidgetData();
+ data.setLayout(CompositeWidgetData.Layout.FLEX_ROW_WRAPPED);
+
+ data.addBlock(new BigNumberBlockData()
+ .withLink("/same-link-for-all-parts")
+ .withTooltip("You can have the same tooltip for all parts")
+ .withStyles(new BigNumberStyles().withWidth("300px"))
+ .withValues(new BigNumberValues().withNumber("123").withHeading("Big Number with Simple Context").withContext("context")));
+
+ data.addBlock(new CompositeWidgetData()
+ .withLayout(CompositeWidgetData.Layout.FLEX_ROW_SPACE_BETWEEN)
+ .withBlock(new BigNumberBlockData()
+ .withLink("/default-link")
+ .withTooltip("You can have a default tooltip...")
+ .withStyles(new BigNumberStyles().withWidth("300px"))
+ .withValues(new BigNumberValues().withNumber("1,234").withHeading("Number with Up/Down Context")))
+ .withBlock(new UpOrDownNumberBlockData()
+ .withTooltip(UpOrDownNumberSlots.CONTEXT, "You can do a custom tooltip for each slot")
+ .withTooltip(UpOrDownNumberSlots.NUMBER, "This number has a customized color")
+ .withLink(UpOrDownNumberSlots.NUMBER, "/custom-link-per-slot")
+ .withStyles(new UpOrDownNumberStyles().withColorOverride("blue"))
+ .withValues(new UpOrDownNumberValues().withIsUp(false).withIsGood(false).withNumber("12,345").withContext("context")))
+ );
+
+ data.addBlock(new CompositeWidgetData()
+ .withLayout(CompositeWidgetData.Layout.FLEX_ROW_SPACE_BETWEEN)
+ .withBlock(new BigNumberBlockData()
+ .withStyles(new BigNumberStyles().withWidth("300px"))
+ .withValues(new BigNumberValues().withNumber("1,234").withHeading("Number with Stacked Up/Down Context")))
+ .withBlock(new UpOrDownNumberBlockData()
+ .withStyles(new UpOrDownNumberStyles().withIsStacked(true))
+ .withValues(new UpOrDownNumberValues().withIsUp(true).withIsGood(true).withNumber("123").withContext("context")))
+ );
+
+ return (new RenderWidgetOutput(data));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleHTMLWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleHTMLWidgetMetaDataProducer.java
new file mode 100644
index 00000000..277efefa
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleHTMLWidgetMetaDataProducer.java
@@ -0,0 +1,75 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.NoCodeWidgetRenderer;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode.HtmlWrapper;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode.QNoCodeWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode.WidgetHtmlLine;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleHTMLWidget
+ *******************************************************************************/
+public class SampleHTMLWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleHTMLWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ QNoCodeWidgetMetaData widgetMetaData = (QNoCodeWidgetMetaData) new QNoCodeWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.HTML.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("HTML")
+ .withTooltip("This is a sample of an HTML widget")
+ .withShowReloadButton(false)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_RIGHT_INSIDE_CARD, new QIcon("data_object").withColor("#D87E28"))
+ .withCodeReference(new QCodeReference(NoCodeWidgetRenderer.class));
+
+ widgetMetaData.withOutput(new WidgetHtmlLine()
+ .withWrapper(HtmlWrapper.BIG_CENTERED)
+ .withVelocityTemplate("Purely Custom"));
+
+ widgetMetaData.withOutput(new WidgetHtmlLine()
+ .withVelocityTemplate("User Defined HTML"));
+
+ return widgetMetaData;
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleLineChartWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleLineChartWidgetMetaDataProducer.java
new file mode 100644
index 00000000..6f595a82
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleLineChartWidgetMetaDataProducer.java
@@ -0,0 +1,85 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.ChartData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleLineChartWidget
+ *******************************************************************************/
+public class SampleLineChartWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleLineChartWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.LINE_CHART.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Line Chart")
+ .withTooltip("This is a sample of a Line Chart widget")
+ .withShowReloadButton(false)
+ .withCodeReference(new QCodeReference(SampleLineChartWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleLineChartWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ List labels = List.of("January", "February", "March", "April", "May");
+ List data = List.of(1753, 1830, 920, 1543, 1804);
+
+ String description = "Total units have been increasing over the last five months.";
+ return (new RenderWidgetOutput(new ChartData("Line Chart", description, "Units", labels, data)));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleMultiStatisticsWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleMultiStatisticsWidgetMetaDataProducer.java
new file mode 100644
index 00000000..bdbdf868
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleMultiStatisticsWidgetMetaDataProducer.java
@@ -0,0 +1,112 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.MultiStatisticsData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleMultiStatisticsWidget
+ *******************************************************************************/
+public class SampleMultiStatisticsWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleMultiStatisticsWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.MULTI_STATISTICS.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Multi Statistics")
+ .withTooltip("This is a sample of a multi-statistics widget")
+ .withShowReloadButton(true)
+ // .withIcon(MaterialDashboardIconRoleNames.TOP_RIGHT_INSIDE_CARD, new QIcon("local_shipping").withColor(WidgetConstants.COLOR_NEW_GREEN))
+ .withCodeReference(new QCodeReference(SampleStatisticsWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleStatisticsWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ MultiStatisticsData.StatisticsGroupData thisWeek = new MultiStatisticsData.StatisticsGroupData()
+ .withIcon("check")
+ .withIconColor("green")
+ .withHeader("This Week")
+ .withSubheader("(1/1/24 - 1/7/24")
+ .withStatisticList(List.of(
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Red", 15, null),
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Green", 20, null),
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Blue", 25, null)
+ ));
+
+ MultiStatisticsData.StatisticsGroupData lastWeek = new MultiStatisticsData.StatisticsGroupData()
+ .withIcon("pending")
+ .withIconColor("red")
+ .withHeader("Last Week")
+ .withSubheader("(12/25/23 - 12/31/23")
+ .withStatisticList(List.of(
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Red", 10, null),
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Green", 25, null),
+ new MultiStatisticsData.StatisticsGroupData.Statistic("Blue", 17, null)
+ ));
+
+ MultiStatisticsData multiStatisticsData = new MultiStatisticsData()
+ .withTitle("Sample Multi Statsitics")
+ .withStatisticsGroupData(
+ List.of(
+ thisWeek,
+ lastWeek
+ )
+ );
+ return (new RenderWidgetOutput(multiStatisticsData));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SamplePieChartWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SamplePieChartWidgetMetaDataProducer.java
new file mode 100644
index 00000000..b6659ca0
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SamplePieChartWidgetMetaDataProducer.java
@@ -0,0 +1,134 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.ChartData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.ChartSubheaderData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SamplePieChart
+ *******************************************************************************/
+public class SamplePieChartWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SamplePieChartWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.PIE_CHART.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Pie Chart")
+ .withTooltip("This is a sample of a pie chart")
+ .withShowReloadButton(true)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_RIGHT_INSIDE_CARD, new QIcon("add_alert").withColor("#10B8A6"))
+ .withCodeReference(new QCodeReference(SamplePieChartRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SamplePieChartRenderer extends AbstractWidgetRenderer
+ {
+ private List labels = new ArrayList<>();
+ private List colors = new ArrayList<>();
+ private List data = new ArrayList<>();
+ private List urls = new ArrayList<>();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private void addSlice(String label, String color, Number datum, String url)
+ {
+ labels.add(label);
+ colors.add(color);
+ data.add(datum);
+ urls.add(url);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ addSlice("Apple", "#FF0000", 100, null);
+ addSlice("Orange", "#FF8000", 150, null);
+ addSlice("Banana", "#FFFF00", 75, null);
+ addSlice("Lime", "#00FF00", 100, null);
+ addSlice("Blueberry", "#0000FF", 200, null);
+
+ ChartData chartData = new ChartData()
+ .withChartData(new ChartData.Data()
+ .withLabels(labels)
+ .withDatasets(List.of(
+ new ChartData.Data.Dataset()
+ .withLabel("Pie")
+ .withData(data)
+ .withBackgroundColors(colors)
+ .withUrls(urls)
+ ))
+ );
+
+ ChartSubheaderData chartSubheaderData = new ChartSubheaderData()
+ .withMainNumber(1000)
+ .withVsPreviousNumber(100);
+ // .withMainNumberUrl(mainUrl)
+ // .withPreviousNumberUrl(previousUrl);
+
+ chartSubheaderData.calculatePercentsEtc(true);
+
+ chartData.setChartSubheaderData(chartSubheaderData);
+
+ return (new RenderWidgetOutput(chartData));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleSmallLineChartWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleSmallLineChartWidgetMetaDataProducer.java
new file mode 100644
index 00000000..8df08dc3
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleSmallLineChartWidgetMetaDataProducer.java
@@ -0,0 +1,85 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.ChartData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleSmallLineChartWidget
+ *******************************************************************************/
+public class SampleSmallLineChartWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleSmallLineChartWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.SMALL_LINE_CHART.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Small Line Chart")
+ .withTooltip("This is a sample of a Small Line Chart widget")
+ .withShowReloadButton(false)
+ .withCodeReference(new QCodeReference(SampleSmallLineChartWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleSmallLineChartWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ List labels = List.of("January", "February", "March", "April", "May");
+ List data = List.of(1753, 1830, 920, 1543, 1804);
+
+ String description = "Total units have been increasing over the last five months.";
+ return (new RenderWidgetOutput(new ChartData("Small Line Chart", description, "Units", labels, data)));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStackedBarChartWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStackedBarChartWidgetMetaDataProducer.java
new file mode 100644
index 00000000..9812ada3
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStackedBarChartWidgetMetaDataProducer.java
@@ -0,0 +1,150 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.ChartData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.ChartSubheaderData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SamplePieChart
+ *******************************************************************************/
+public class SampleStackedBarChartWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleStackedBarChartWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.STACKED_BAR_CHART.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Stacked Bar Chart")
+ .withTooltip("This is a sample of a stacked bar chart")
+ .withShowReloadButton(true)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_LEFT_INSIDE_CARD, new QIcon("new_releases").withColor("#6BA47D"))
+ .withCodeReference(new QCodeReference(SampleStackedBarChartRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleStackedBarChartRenderer extends AbstractWidgetRenderer
+ {
+ private List labels = new ArrayList<>();
+ private List colors = new ArrayList<>();
+ private List data = new ArrayList<>();
+ private List urls = new ArrayList<>();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private void addSlice(String label, String color, Number datum, String url)
+ {
+ labels.add(label);
+ colors.add(color);
+ data.add(datum);
+ urls.add(url);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ addSlice("Apple", "#FF0000", 100, null);
+ addSlice("Orange", "#FF8000", 150, null);
+ addSlice("Banana", "#FFFF00", 75, null);
+ addSlice("Lime", "#00FF00", 100, null);
+ addSlice("Blueberry", "#0000FF", 200, null);
+
+ ChartData.Data.Dataset one = new ChartData.Data.Dataset()
+ .withLabel("One")
+ .withData(data)
+ .withBackgroundColors(colors)
+ .withUrls(urls);
+
+ labels = new ArrayList<>();
+ colors = new ArrayList<>();
+ data = new ArrayList<>();
+ urls = new ArrayList<>();
+
+ addSlice("Apple", "#FF0000", 50, null);
+ addSlice("Orange", "#FF8000", 100, null);
+ addSlice("Banana", "#FFFF00", 75, null);
+ addSlice("Lime", "#00FF00", 150, null);
+ addSlice("Blueberry", "#0000FF", 75, null);
+
+ ChartData.Data.Dataset two = new ChartData.Data.Dataset()
+ .withLabel("Two")
+ .withData(data)
+ .withBackgroundColors(colors)
+ .withUrls(urls);
+
+ ChartData chartData = new ChartData()
+ .withChartData(new ChartData.Data()
+ .withLabels(labels)
+ .withDatasets(List.of(one, two)));
+
+ ChartSubheaderData chartSubheaderData = new ChartSubheaderData()
+ .withMainNumber(1000)
+ .withVsPreviousNumber(100);
+ // .withMainNumberUrl(mainUrl)
+ // .withPreviousNumberUrl(previousUrl);
+
+ chartSubheaderData.calculatePercentsEtc(true);
+
+ chartData.setChartSubheaderData(chartSubheaderData);
+
+ return (new RenderWidgetOutput(chartData));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStatisticsWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStatisticsWidgetMetaDataProducer.java
new file mode 100644
index 00000000..bb2781d7
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStatisticsWidgetMetaDataProducer.java
@@ -0,0 +1,87 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.math.BigDecimal;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.StatisticsData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
+import com.kingsrook.qqq.frontend.materialdashboard.model.metadata.MaterialDashboardIconRoleNames;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleStatisticsWidget
+ *******************************************************************************/
+public class SampleStatisticsWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleStatisticsWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.STATISTICS.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Statistics")
+ .withTooltip("This is a sample of a statistics widget")
+ .withShowReloadButton(false)
+ .withIcon(MaterialDashboardIconRoleNames.TOP_LEFT_INSIDE_CARD, new QIcon("assessment").withColor("#0061FF"))
+ .withCodeReference(new QCodeReference(SampleStatisticsWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleStatisticsWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ StatisticsData data = new StatisticsData("98.5%", new BigDecimal("-10.0"), "vs prev week");
+ data.withCountContext("of 481");
+ data.withPercentageURL("http://www.google.com/");
+ return (new RenderWidgetOutput(data));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStepperWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStepperWidgetMetaDataProducer.java
new file mode 100644
index 00000000..10ff5ddf
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleStepperWidgetMetaDataProducer.java
@@ -0,0 +1,92 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.StepperData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleStepperWidget
+ *******************************************************************************/
+public class SampleStepperWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleStepperWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.STEPPER.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Stepper")
+ .withTooltip("This is a sample of a stepper widget")
+ .withShowReloadButton(false)
+ .withCodeReference(new QCodeReference(SampleStepperWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleStepperWidgetRenderer extends AbstractWidgetRenderer
+ {
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ List stepperDataList = List.of(
+ new StepperData.Step().withLabel("Step 1: Underpants").withLinkText("Underpants").withLinkURL("http://www.google.com"),
+ new StepperData.Step().withLabel("Step 2").withLinkText("??").withLinkURL("http://www.google.com"),
+ new StepperData.Step().withLabel("Step 3: Profit").withLinkText("Profit").withLinkURL("http://www.google.com")
+ );
+
+ StepperData stepper = new StepperData(
+ "Sample Stepper Widget",
+ 1,
+ stepperDataList
+ );
+ return (new RenderWidgetOutput(stepper));
+ }
+ }
+
+}
diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleTableWidgetMetaDataProducer.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleTableWidgetMetaDataProducer.java
new file mode 100644
index 00000000..aff604ff
--- /dev/null
+++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/metadata/widgetsdashboard/SampleTableWidgetMetaDataProducer.java
@@ -0,0 +1,127 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2024. 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.sampleapp.metadata.widgetsdashboard;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
+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.TableData;
+import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
+import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
+import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
+
+
+/*******************************************************************************
+ ** Meta Data Producer for SampleStatisticsWidget
+ *******************************************************************************/
+public class SampleTableWidgetMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "SampleTableWidget";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QWidgetMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QWidgetMetaData()
+ .withName(NAME)
+ .withType(WidgetType.TABLE.getType())
+ .withGridColumns(4)
+ .withIsCard(true)
+ .withLabel("Table")
+ .withTooltip("This is a sample of a table widget")
+ .withShowReloadButton(false)
+ .withCodeReference(new QCodeReference(SampleTableWidgetRenderer.class));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public static class SampleTableWidgetRenderer extends AbstractWidgetRenderer
+ {
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public RenderWidgetOutput render(RenderWidgetInput input) throws QException
+ {
+ ////////////////////////////////////
+ // setup datastructures for table //
+ ////////////////////////////////////
+ List