• Rendered into HTML

  • Rendered into PDF

  • Rendered into Mails

  • Rendered into CSV

Diagram DSL allows quickly drawing bar, area, pie, scatter, line, whiskers and timeline diagrams, possibly mixed, either rasterized in PNG or in SVG format.

In a block, a diagram is added via diagram, which takes either an UiDiagramSpecifier or a MethodClosure returning one, or via diagramFilter to associate it with a filter.

Chart Sample

Bar

Example 1. Bar chart
Barchart Code Sample
private static UiDiagramSpecifier barDiagram(boolean isStacked) {
    new UiDiagramSpecifier().ui {
        bar(isStacked, {
            labels "T1", "T2", "T3", "T4"
            dataset 'Truc1', 1.0, 2.0, 1.0, 4.0
            dataset 'Truc2', 2.0, 0.1, 1.0, 0.0
            dataset 'Truc3', 2.0, 0.1, 1.0, 1.0
        })
    }
}
Result

diag dsl bar

Line

Example 2. Line chart
Lines Code Sample
diagram new UiDiagramSpecifier().ui({
    line {
        labels 1.5, 3, 4.4, 5, 7.8, 8
        dataset "client", 10.0, 20.1, 30.0
        dataset "admin", 5.0, 7.0
        dataset "other", 1.0, 2.0, 3.0, 4.0, 5.0, 6.0
    }
})
Result

diag dsl line

Pie

Example 3. Pie chart
Pie Code Sample
private static UiDiagramSpecifier pieDiagram(boolean hasSlice) {
    new UiDiagramSpecifier().ui({
        pie(hasSlice, {
            labels "Pie"
            dataset("cli", 1.47)
            dataset("client", 0.28)
            dataset("client1", 0.1)
            dataset("client2", 1.45)
            dataset("client3", 0.05)
            dataset("client31", 0.05)
            dataset("client32", 0.05)
            dataset("c33", 0.05)
            dataset("client311", 0.05)
            dataset("client312", 0.05)
            dataset("client313", 0.05)
            dataset("client4", 0.8)
            dataset("client5", 2.1)
            dataset("client55", 0.1)
            dataset("client555", 0.2)
            dataset("client5555", 0.3)
            dataset("client55555", 0.3)
            dataset("admin", 1.6)
            dataset("test1", 0.05)
        })
    })
}
Result

diag dsl pie

Whiskers

Example 4. Whiskers chart
Whiskers Code Sample
diagram new UiDiagramSpecifier().ui({
    whiskers {
        labels "T1", "T2", "T3", "T4"

        dataset 'Truc1', {
            boxData 1.0, 2.0, 3.0, 3.5, 4.0, 4.5, 5.0
            boxData 1.5, 2.5, 3.5, 6.0, 7.0, 8.0, 9.0
            boxData 2.0, 2.0, 2.1, 2.5, 5.5, 5.6, 6.7
            boxData 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3
        }
        dataset 'Truc2', {
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
        }
    }
})
Result

diag dsl whiskers

Timeline

Example 5. Timeline chart
Timeline Code Sample
diagram new UiDiagramSpecifier().ui({
    timeline {
        SimpleDateFormat format = new SimpleDateFormat('yyyy-MM-dd')
        dataset 'Truc1', {
            periodData format.parse('2025-06-12'), format.parse('2025-07-08'), "Period1"
            periodData format.parse('2025-07-08'), format.parse('2025-07-21'), "Period2"
            periodData format.parse('2025-07-21'), format.parse('2025-08-30'), "Period3"
        }
        dataset 'Truc2', {
            periodData format.parse('2025-06-20'), format.parse('2025-06-25'), "Period1"
            periodData format.parse('2025-07-01'), format.parse('2025-07-21'), "Period2"
        }
    }
})
Result

diag dsl timeline

Mixed

Other diagram types can be nested into a diagram closure. They share the labels of the X axis and the legend, each nested type having its own Y axis, colored like its datasets.

Example 6. Mixed chart
Mixed Code Sample
diagram new UiDiagramSpecifier().ui {
    bar {                                                           (1)
        labels 'W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8'
        dataset 'Line A', 55.0, 62.0, 58.0, 70.0, 74.0, 61.0, 80.0, 77.0
        dataset 'Line B', 40.0, 48.0, 44.0, 58.0, 61.0, 57.0, 70.0, 65.0
        line {                                                      (2)
            dataset 'Scrap rate (%)', 2.1, 1.8, 2.5, 1.6, 1.4, 2.9, 1.2, 1.5
        }
        scatter {                                                   (3)
            dataset 'Downtime (h)', 4.0, 6.0, 3.0, 8.0, 5.0, 2.0, 7.0, 4.0
        }
        option DiagramOption.builder
                .setTitle('Weekly production')
                .build()
    }
}
1 Main diagram, defining the labels on X axis (here a stacked bar chart)
2 Nested line, drawn over the bars with its own Y axis on the right
3 Nested scatter, with its own Y axis on the left
Result

diag dsl mixed

Customized Option

We give various options to allow user to customize the chart, by using DiagramOption.

Barchart using DiagramOption
private static UiDiagramSpecifier barDiagram(boolean isStacked) {
    new UiDiagramSpecifier().ui {
        bar(isStacked, {
            labels "T1", "T2", "T3", "T4"
            dataset 'Truc1', 1.0, 2.0, 1.0, 4.0
            dataset 'Truc2', 2.0, 0.1, 1.0, 0.0
            dataset 'Truc3', 2.0, 0.1, 1.0, 1.0

            option DiagramOption.builder
                    .setTitle("This is a Bar chart !")
                    .hideLegend()
                    .showDataCount()
                    .setKeyColors(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN)
                    .setClickAction(Pr2Controller.&onclickBar as MethodClosure)
                    .setResolution(DiagramResolution.DEFAULT_2K)
                    .build()
        })
    }
}
Result

diag dsl bar option

Available options:

  • setTitle: diagram title

  • hideLegend: legends are shown by default

  • showDataCount: show the values on the diagram (hidden by default)

  • setKeyColors: colors of each dataset (7 colors by default)

  • setClickAction: action called when clicking on a shape, it receives key (dataset name), x and y params, plus the given id and params (see Clickable Diagram)

  • setResolution: default resolution is SVG: 960x540, from DEFAULT_540P to DEFAULT_4K

  • setXLabelDateFormat: see Different types of xLabels

  • setMaxDataNumberToShowByDefault: limit the number of data displayed before zooming

  • showTodayLine: timeline only, draw a line at the current date

Clickable Diagram

When a click action is set, clicking on a shape (bar, point, slice, box, period …​) calls the action via Ajax. The action can return a block, typically a modal, or a full page that will be opened in a new tab.

Opening a modal when clicking on a bar
def salesPerMonth() {
    taackUiService.show(new UiBlockSpecifier().ui {
        diagram new UiDiagramSpecifier().ui {
            bar false, {
                labels 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'
                dataset 'Bikes', 12.0, 18.0, 9.0, 21.0, 25.0, 30.0
                dataset 'Scooters', 7.0, 5.0, 11.0, 8.0, 14.0, 12.0
                option DiagramOption.builder
                        .setTitle('Units sold per month')
                        .setClickAction(SalesController.&salesDetail as MC,  (1)
                                [year: 2026])
                        .build()
            }
        }
    }, buildMenu())
}

def salesDetail(String key, String x, String y, Integer year) {         (2)
    int units = new BigDecimal(y).intValue()
    Map<String, Integer> orders = [                                     (3)
            'Acme Corp': units.intdiv(2) as Integer,
            'Globex'   : units.intdiv(3) as Integer,
            'Initech'  : units - units.intdiv(2) - units.intdiv(3)
    ]
    taackUiService.show(new UiBlockSpecifier().ui {
        modal {                                                         (4)
            show new UiShowSpecifier().ui {
                field 'Product', key
                field 'Month', "$x $year".toString()
                field 'Units sold', y
            }
            table new UiTableSpecifier().ui {
                header {
                    label 'Order'
                    label 'Customer'
                    label 'Units'
                }
                orders.eachWithIndex { Map.Entry<String, Integer> o, int i ->
                    row {
                        rowField "SO-$year-$x-${i + 1}".toString()
                        rowField o.key
                        rowField o.value
                    }
                }
            }
        }
    })
}
1 Action called on click, with optional params (or an id)
2 key is the dataset name, x the label on X axis and y the value, year comes from the params given to setClickAction
3 Fictional data, usually a query on your domain objects
4 The action answers a modal, displayed above the diagram
diag dsl click modal
Figure 1. Click on the "Bikes" bar of May

Bonus way to code

Different types of xLabels

The labels on X axis could be of 3 types:

  • String (Discrete)

  • Number (Continuous)

  • Date (Continuous)

diagram new UiDiagramSpecifier().ui({
    line { // X axis: String
        labels "T1", "T2", "T3"
        dataset "test", 10.0, 20.1, 30.0
    }
    line { // X axis: Number
        labels 1.5, 1.7, 3.5
        dataset "test", 10.0, 20.1, 30.0
    }
    line { // X axis: Date
        Date date1 = new Date() // now (2025-02-28 10:55)
        Date date2 = new Date(date1.getTime() + 1000*60*60*2) // 2 hours later
        Date date3 = new Date(date1.getTime() + 1000*60*60*10) // 10 hours later
        labels date1, date2, date3
        dataset "test", 10.0, 20.1, 30.0
        option DiagramOption.builder
                .setXLabelDateFormat(DiagramXLabelDateFormat.HOUR) (1)
                .build()
    }
})
1 DiagramXLabelDateFormat: Define the date format to display, and also define the minimum gap unit (Because X axis is continuous)

screenshot dsl diagram xLabels type

Second way to give data coordinate

Often used for continuous X axis on which datasets have different X coordinate.

diagram new UiDiagramSpecifier().ui({
    // Normal way: different datasets have same X coordinates
    line {
        labels 1.5, 1.7, 3.5

        // 3 data: (1.5, 10.0), (1.7, 20.1), (3.5, 30.0)
        dataset "test1", 10.0, 20.1, 30.0

        // 3 data: (1.5, 1.0), (1.7, 2.0), (3.5, 3.0)
        dataset "test2", 1.0, 2.0, 3.0
    }

    // Second way: different datasets have different X coordinates
    line {
        // 3 data: (1.5, 10.0), (1.7, 20.1), (3.5, 30.0)
        dataset "test1", [1.5: 10.0, 1.7: 20.1, 3.5: 30.0]

        // 2 data: (1.5, 1.0), (6.1, 2.0)
        dataset "test2", [1.5: 1.0, 6.1: 2.0]
    }
})

screenshot dsl diagram coordinate

DSL to show data count at regular intervals

We have a large number of objects, and we would like to have a diagram that shows the number of objects year-by-year (or month-by-month / day-by-day / hour-by-hour) depending on object’s dateCreated.

DSL to use
    /**
     * Group the given dates according to DiagramXLabelDateFormat, then count every group and put the result as data to draw.
     *
     * For example:
     *      Knowing DiagramXLabelDateFormat.MONTH (Defined by {@link #labels(DiagramXLabelDateFormat dateFormat)}),
     *      and being given dates: 2025-01-01, 2025-01-10, 2025-01-20, 2025-02-01, 2025-02-10, 2025-03-01.
     *
     *      So they are divided to 3 groups with their own count: [2025-01: 3, 2025-02: 2, 2025-03: 1].
     *      The groups will be used as data to draw:
     *          - xLabels = ["2025-01", "2025-02", "2025-03"]
     *          - yDataList = [3.0, 2.0, 1.0]
     *
     * @param key
     * @param dates
     */
    void dataset(final String key, final Date... dates)
Code how to use the DSL
diagram new UiDiagramSpecifier().ui({
    List<Claim> claims = Claim.findAll()
    bar {
        dataset "Claim", claims.collect { it.dateCreated } as Date[]
        option DiagramOption.builder
                .setXLabelDateFormat(DiagramXLabelDateFormat.MONTH) // show claim count month-by-month
                .build()
    }
})
Diagram

screenshot dsl diagram count object

Dynamic parts (Only in HTML)

Zoom (Horizontally)

Put mouse on diagram, then scroll the mouse wheel with CTRL pressed.

  • CTRL + Wheel-up for Zoom-up.

  • CTRL + Wheel-down for Zoom-down.

Scroll (Horizontally)

Put mouse on diagram, press the left mouse button and keep pressing, then move mouse horizontally.

Scroll min and max are limited

Tooltip

The value of barchart/line/…​ will not be shown statically. Instead, we can put mouse on any shape, then a tooltip will appear dynamically that shows all information about the target shape.

screenshot dsl diagram tooltip

Clickable legend

Click on a dataset legend allows us to hide the showing of target dataset.

DSL Symbols Hierarchy

Diagram
Figure 2. Symbol hierarchy diagram for Diagram DSL