TotalBase
Widgets

Editing a Widget

The widget drawer: its query, the preview, Properties and Styles.

In the admin: a Dashboard › a widget › Edit

Edit on a card's ⋮, Configure on a new one, or a double-click on its header opens the widget drawer. On the left, the preview and the SQL editor; on the right, the inspector with Properties and Styles. Nothing is saved until Save; Cancel leaves the widget as it was.

On a phone, three tabs replace the two sides: Query, Preview and Settings.

The widget drawer for Open orders by status: the donut preview, its query and the inspector.
The widget drawer for Open orders by status: the donut preview, its query and the inspector.

The query

Write a SELECT in the editor. Opening a widget that has a query runs it at once. The toolbar:

Runruns the query as typed, with the variables bar's current values. Ctrl+Enter does the same. The preview redraws from the result
row count24 rows · 85 ms, marked (cut off at dashboards.query_max_rows) when the result reached the row cap
Wrapwraps long lines. On by default on a touch device or a narrow screen
Examplewhat this type expects and a query that runs anywhere, with Use this query
Optional filterwrites the standard filter for a variable at the cursor (below). Only when the dashboard has variables
Resultsshows the raw rows in a grid, to check columns and values

Optional filter

Pick a Variable and a Column (or an expression such as wo.reported_at), and Insert writes the condition for its type:

VariableInserted
Date range($VAR.period.from IS NULL OR wo.reported_at >= $VAR.period.from) AND ($VAR.period.to IS NULL OR wo.reported_at < $VAR.period.to)
Select($VAR.status IS NULL OR wo.status = $VAR.status); with several values, = ANY($VAR.status)
Text($VAR.search IS NULL OR c.name ILIKE '%' || $VAR.search || '%')
Number($VAR.year IS NULL OR extract(year FROM i.issued_on) = $VAR.year)

While the variable has no value, the condition lets every row through. It's plain SQL: TotalBase never rewrites it.

A Select variable is text. To compare it with a uuid column, cast it: ($VAR.branch IS NULL OR wo.branch = $VAR.branch::uuid).

How a query runs

The guarantees come from PostgreSQL, not from inspecting the SQL:

  • Read-only. Each run is its own READ ONLY transaction. An INSERT, UPDATE, DELETE, a data-modifying WITH or a write inside a called function fails with SQLSTATE 25006.
  • Always rolled back. The transaction never commits, so even a changed session setting doesn't outlive it.
  • One statement. Stacked statements (SELECT 1; DELETE ...) are refused before anything runs. A trailing ; is fine.
  • A time limit. PostgreSQL cancels a query that runs longer than the instance's timeout (10 seconds by default).
  • A row cap. At most the instance's row cap (1000 rows by default); the rest are cut, never paged, and the card says so.
  • The viewer's time zone. now(), date_trunc and the date range presets cut days and months where the viewer lives.

The timeout and the row cap are instance settings: see Settings › Dashboards.

Variables are bound

$VAR.<name> and $USER.<column> become typed parameters: a text a viewer types is compared as a value, never run as SQL. $USER.<column> takes the column's real type and is read from the viewer's current row on every run; in the editor it's you. $USER.password_hash is refused, as is a variable the dashboard doesn't define or a hand-written $1. $INTERVAL and $PERIOD don't exist here: use PostgreSQL's now() - interval '7 days' and a Date range variable.

Properties

Type

The widget's type, by group. Once the query has run, a type that doesn't fit what it returns is greyed, with why: Bar chart needs at least one column of a number for Values. Switching keeps the query, the settings both types share and the equivalent columns (a chart's Category becomes a pie's Category, its Values the Value).

Title

The card's title. Empty, a data widget shows its type's name. The link button (Bind) beside it turns the title into a formula over the variables, the viewer and the query's first row: "Orders of " + {{vars.branch.label}}. When the formula gives a text, it wins over the literal title.

Data

A field per role: what each result column does in the widget, such as a chart's Category and Values. Each field offers only the columns of a kind it takes, each shown with its type and the table column it comes from. Unset, it says what it takes on its own: Automatic: total - the first matching column. Roles never pick a column by its name, and never a column starting with _.

Back to automatic (⊘) clears a choice. A role with several columns lists them in order: drag to reorder, Add a column… to add one. A column the query no longer returns is marked in error.

The type's own settings

Then the type's settings, in sections, only those the type has: Number format, Appearance, Series, Axes, Thresholds, Events, Zoom & export. A setting shows its default while unset; ⊘ returns it to the default. Each group's page lists them.

Number format shows the value column's own format greyed when it has one (Inherited from the column (total)…), with Edit in the table to change it for every screen. A format is a pattern: $ #,##0, #,##0.00, 0.0 % (the % doesn't multiply: 85 reads 85.0 %), CURRENCY:ARS. Compact number abbreviates large numbers (11.6M) and is on unless a format applies.

Events

On click sets what a click on a mark, a row or the card does:

ActionDoes
Filter this dashboardsets one of its Select, Text or Number variables. In the App, Back takes it off
Open a DataViewopens it filtered, with a filter in the Data API's where grammar
Open a dashboardopens another dashboard with its variables set, on a tab
Open a recordopens a DataView's record form by its key
Open a URLopens an https address, in a new tab if you choose. Also in embeds lets it run in a public link or signed embed

Values are formulas over the clicked row, {{row.<column>}} (its _ columns included), and the variables, {{vars.<name>}}. Tooltip line is the hint viewers see on hover. Only Filter and a URL marked Also in embeds run in an embed.

Card

Setting
Descriptionshown behind an ⓘ next to the title: what the widget measures
Text with no datawhat it says with no rows. Default: No data for this period when the query reads a date range, else No data
On a phoneAutomatic (half for a widget a quarter of the desktop wide or less, else the whole width), Whole width, Half, Hidden

The inspector's ⋮ has Restore defaults: it clears the type's settings and keeps the card settings, the styles and the title's formula.

Styles

The common style block of every widget: margin, padding, border, radius, background, shadow and alignment, applied to the widget's body.

Next steps