mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
225 lines
7.9 KiB
Plaintext
225 lines
7.9 KiB
Plaintext
== Rendering Widgets
|
|
include::../variables.adoc[]
|
|
|
|
=== WidgetRenderer classes
|
|
In general, to fully implement a Widget, you must define its `QWidgetMetaData`,
|
|
and supply a subclass of `AbstractWidgetRenderer`, to provide the data to the widget.
|
|
(Note the "No Code" category of widgets, which are an exception to this generalization).
|
|
|
|
The only method required in a subclass of `AbstractWidgetRenderer` is:
|
|
|
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
|
|
|
The fields available in `RenderWidgetInput` are:
|
|
|
|
- `Map<String, String> queryParams` - These are parameters supplied by the frontend, for example,
|
|
if a user selected values from dropdowns to control a dimension of your widget, those name/value
|
|
pairs would be in this map. Similarly, if your widget is being included on a record view screen, then
|
|
the record's primary key will be in this map.
|
|
- `QWidgetMetaDataInterface widgetMetaData` - This is the meta-data for the widget being
|
|
rendered. This can be useful in case you are using the same renderer class for multiple widgets.
|
|
|
|
The only field in `RenderWidgetOutput` is:
|
|
|
|
- `QWidgetData widgetData` - This is a base class, with several attributes, and more importantly,
|
|
several subclasses, specific to the type of widget that is being rendered.
|
|
|
|
==== Widget-Type Specific Rendering Details
|
|
Different widget types expect & require different types of values to be set in the `RenderWidgetOutput` by their renderers.
|
|
|
|
===== Pie Chart
|
|
The `WidgetType.PIE_CHART` requires an object of type `ChartData`.
|
|
The fields on this type are:
|
|
|
|
* `chartData` an instance of `ChartData.Data`, which has the following fields:
|
|
** `labels` - *List<String>, required* - the labels for the slices of the pie.
|
|
** `datasets` - *List<Dataset> required* - the data for each slice of the pie.
|
|
For a Pie chart, only a single entry in this list is used
|
|
(other chart types using `ChartData` may support more than 1 entry in this list).
|
|
Fields in this object are:
|
|
*** `label` - *String, required* - a label to describe the dataset as a whole.
|
|
e.g., "Orders" for a pie showing orders of different statuses.
|
|
*** `data` - *List<Number>, required* - the data points for each slice of the pie.
|
|
*** `color` - *String* - HTML color for the slice
|
|
*** `urls` - *List<String>* - Optional URLs for slices of the pie to link to when clicked.
|
|
*** `backgroundColors` - *List<String>* - Optional HTML color codes for each slice of the pie.
|
|
|
|
[source,java]
|
|
.Pie chart widget example
|
|
----
|
|
// meta data
|
|
new QWidgetMetaData()
|
|
.withName("pieChartExample")
|
|
.withType(WidgetType.PIE_CHART.getType())
|
|
.withGridColumns(4)
|
|
.withIsCard(true)
|
|
.withLabel("Pie Chart Example")
|
|
.withCodeReference(new QCodeReference(PieChartExampleRenderer.class));
|
|
|
|
// renderer
|
|
private List<String> labels = new ArrayList<>();
|
|
private List<String> colors = new ArrayList<>();
|
|
private List<Number> data = new ArrayList<>();
|
|
|
|
/*******************************************************************************
|
|
** helper method - to add values for a slice to the lists
|
|
*******************************************************************************/
|
|
private void addSlice(String label, String color, Number datum)
|
|
{
|
|
labels.add(label);
|
|
colors.add(color);
|
|
data.add(datum);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
** main method of the widget renderer
|
|
*******************************************************************************/
|
|
@Override
|
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
|
{
|
|
addSlice("Apple", "#FF0000", 100);
|
|
addSlice("Orange", "#FF8000", 150);
|
|
addSlice("Banana", "#FFFF00", 75);
|
|
addSlice("Lime", "#00FF00", 100);
|
|
addSlice("Blueberry", "#0000FF", 200);
|
|
|
|
ChartData chartData = new ChartData()
|
|
.withChartData(new ChartData.Data()
|
|
.withLabels(labels)
|
|
.withDatasets(List.of(
|
|
new ChartData.Data.Dataset()
|
|
.withLabel("Flavor")
|
|
.withData(data)
|
|
.withBackgroundColors(colors)
|
|
.withUrls(urls))));
|
|
|
|
return (new RenderWidgetOutput(chartData));
|
|
}
|
|
|
|
----
|
|
|
|
===== Bar Chart
|
|
#todo#
|
|
|
|
===== Stacked Bar Chart
|
|
#todo#
|
|
|
|
===== Horizontal Bar Chart
|
|
#todo#
|
|
|
|
===== Child Record List
|
|
#todo#
|
|
|
|
===== Line Chart
|
|
#todo#
|
|
|
|
===== Small Line Chart
|
|
#todo#
|
|
|
|
===== Statistics
|
|
#todo#
|
|
|
|
===== Parent Widget
|
|
#todo#
|
|
|
|
===== Composite
|
|
A `WidgetType.COMPOSITE` is built by using one or more smaller elements, known as `Blocks`.
|
|
Note that `Blocks` can also be used in the data of some other widget types
|
|
(specifically, within a cell of a Table-type widget, or (in the future?) as a header above a pie or bar chart).
|
|
|
|
A composite widget renderer must return data of type `CompositeWidgetData`,
|
|
which has the following fields:
|
|
|
|
* `blocks` - *List<AbstractBlockWidgetData>, required* - The blocks (1 or more) being composited together to make the widget.
|
|
See below for details on the specific Block types.
|
|
* `styleOverrides` - *Map<String, Serializable>* - Optional map of CSS attributes
|
|
(named following javascriptStyleCamelCase) to apply to the `<div>` element that wraps the rendered blocks.
|
|
* `layout` - *Layout enum* - Optional specifier for how the blocks should be laid out.
|
|
e.g., predefined sets of CSS attributes to achieve specific layouts.
|
|
** Note that some blocks are designed to work within composites with specific layouts.
|
|
Look for matching names, such as `Layout.BADGES_WRAPPER` to go with `NumberIconBadgeBlock`.
|
|
|
|
[source,java]
|
|
.Composite widget example - consisting of 3 Progress Bar Blocks, and one Divider Block
|
|
----
|
|
// meta data
|
|
new QWidgetMetaData()
|
|
.withName("compositeExample")
|
|
.withType(WidgetType.COMPOSITE.getType())
|
|
.withGridColumns(4)
|
|
.withIsCard(true)
|
|
.withLabel("Composite Example")
|
|
.withCodeReference(new QCodeReference(CompositeExampleRenderer.class));
|
|
|
|
// renderer
|
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
|
{
|
|
CompositeWidgetData data = new CompositeWidgetData();
|
|
|
|
data.addBlock(new ProgressBarBlockData()
|
|
.withValues(new ProgressBarValues()
|
|
.withHeading("Blocks")
|
|
.withPercent(new BigDecimal("78.5"))));
|
|
|
|
data.addBlock(new ProgressBarBlockData()
|
|
.withValues(new ProgressBarValues()
|
|
.withHeading("Progress")
|
|
.withPercent(new BigDecimal(0))));
|
|
|
|
data.addBlock(new DividerBlockData());
|
|
|
|
data.addBlock(new ProgressBarBlockData()
|
|
.withStyles(new ProgressBarStyles().withBarColor("#C0C000"))
|
|
.withValues(new ProgressBarValues()
|
|
.withHeading("Custom Color")
|
|
.withPercent(new BigDecimal("75.3"))));
|
|
|
|
return (new RenderWidgetOutput(data));
|
|
}
|
|
----
|
|
|
|
|
|
===== Table
|
|
#todo#
|
|
|
|
===== HTML
|
|
#todo#
|
|
|
|
===== Divider
|
|
#todo#
|
|
|
|
===== Process
|
|
#todo#
|
|
|
|
===== Stepper
|
|
#todo#
|
|
|
|
===== Data Bag Viewer
|
|
#todo#
|
|
|
|
===== Script Viewer
|
|
#todo#
|
|
|
|
=== Block-type Specific Rendering Details
|
|
For Composite-type widgets (or other widgets which can include blocks),
|
|
there are specific data classes required to be returned by the widget renderer.
|
|
|
|
Each block type defines a subclass of `AbstractBlockWidgetData`,
|
|
which is a generic class with 3 type parameters:
|
|
|
|
* `V` - an implementation of `BlockValuesInterface` - to define the type of values that the block uses.
|
|
* `S` - an implementation of `BlockSlotsInterface` (expected to be an `enum`) - to define the "slots" in the block,
|
|
that can have Tooltips and/or Links applied to them.
|
|
* `SX` - an implementation of `BlockStylesInterface` - to define the types of style customizations that the block supports.
|
|
|
|
These type parameters are designed to ensure type-safety for the application developer,
|
|
to ensure that only
|
|
|
|
=== Additional Tips
|
|
|
|
* To make a Dashboard page (e.g., an App consisting of Widgets) with a parent widget use the parent widget's label as the page's label:
|
|
** On the `QAppMetaData` that contains the Parent widget, call
|
|
`.withSupplementalMetaData(new MaterialDashboardAppMetaData().withShowAppLabelOnHomeScreen(false))`.
|
|
** In the Parent widget's renderer, on the `ParentWidgetData`, call `setLabel("My Label")` and
|
|
`setIsLabelPageTitle(true)`.
|