Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jenkinsci/data-tables-api-plugin

Jenkins plug-that provides JQuery DataTables
https://github.com/jenkinsci/data-tables-api-plugin

api-plugin datatables jenkins-plugin jquery

Last synced: about 1 month ago
JSON representation

Jenkins plug-that provides JQuery DataTables

Awesome Lists containing this project

README

        

:tip-caption: :bulb:
:imagesdir: etc/images

= jQuery DataTables Jenkins Plugin

image:https://ci.jenkins.io/job/Plugins/job/data-tables-api-plugin/job/main/badge/icon?subject=Jenkins%20CI[Jenkins, link=https://ci.jenkins.io/job/Plugins/job/data-tables-api-plugin/job/main/]
image:https://github.com/jenkinsci/data-tables-api-plugin/workflows/GitHub%20CI/badge.svg[GitHub Actions, link=https://github.com/jenkinsci/data-tables-api-plugin/actions]
image:https://img.shields.io/github/issues-pr/jenkinsci/data-tables-api-plugin.svg[GitHub pull requests, link=https://github.com/jenkinsci/data-tables-api-plugin/pulls]

Provides https://datatables.net[jQuery DataTables] for Jenkins Plugins. DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, built upon the foundations of progressive enhancement, that adds all of these advanced features to any HTML table:

** Previous, next and page navigation
** Filter results by text search
** Sort data by multiple columns at once
** DOM, Javascript, Ajax and server-side processing
** Easily theme-able
** Mobile friendly

This plugin contains JS and CSS files of the latest https://datatables.net[DataTables] release and corresponding Jenkins UI elements (Java data model). It also contains some additional DataTables plugins.

== How to use the plugin

A common UI element to show plugin details is a table control. Most plugins (and Jenkins core) typically use
plain HTML tables. However, if the table should show a large number of rows then using a more sophisticated control
like https://datatables.net[DataTables] makes more sense.

In order to use https://datatables.net[DataTables] in a view there are two options, you can either decorate existing
static HTML tables (see <>) or populate the table content using Ajax (see <>). Both
option require that you add a maven dependency to your pom:

[source,xml]
----

io.jenkins.plugins
data-tables-api
[latest version]

----

[#tables-static]
=== Tables with static HTML content

The easiest way of using DataTables is by creating a static HTML table that will be decorated by simply calling the
constructor of the datatable. This approach involves no special handling on the Java and Jelly side, so I think it is
sufficient to follow the https://datatables.net/examples/basic_init/zero_configuration.html[example] in the DataTables
documentation. Just make sure that after building the table in your Jelly file you need to decorate the table
with the following piece of code:

[source,xml]
----


[...]



[...]

[...]

$('#id').DataTable(); <1>

----
<1> replace `id` with the ID of your HTML table element

In the Forensics plugin no such static table is used so far, but you can have a look at the
https://github.com/jenkinsci/warnings-ng-plugin/blob/master/plugin/src/main/resources/io/jenkins/plugins/analysis/core/model/FixedWarningsDetail/index.jelly[table that shows fixed warnings]
in the warnings plugin to see how such a table can be decorated.

[#tables-dynamic]
=== Tables with dynamic model based content

While static HTML tables are easy to implement, they have several limitations. So it makes sense to follow a more
sophisticating approach. Typically, tables in user interfaces are defined by using a corresponding table (and row) model.
Java Swing successfully provides such a
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html[table model] concept since the early days of Java.
I adapted these concepts for Jenkins and DataTables as well. In order to create a table in a Jenkins view a plugin
needs to provide a table model class, that provides the following information:

- the ID of the table (since there might be several tables in the view)
- the model of the columns (i.e., the number, type, and header labels of the columns)
- the content of the table (i.e. the individual row objects)

You will find an example of such a table in the Forensics plugin: here a table lists
the files in your Git repository combined with the corresponding commit statistics (number of authors,
number of commits, last modification, first commit). A screenshot of that table is shown in <>.

.Dynamic Table in the Forensics plugin
[#img-table]
image::table.png[Table example]

In order to create such a table in Jenkins, you need to create a table model class that derives from `TableModel`.
In <> a diagram of the corresponding classes in the Forensics plugin is shown.

[#forensics-table-model]
.Table model of the Forensics plugin
image::table-model.png[Tabel model]

==== Table column model

This first thing a table model class defines is a model of the available columns by creating corresponding
`TableColumn` instances. For each column you need to specify a header label and the name of the bean property that
should be shown in the corresponding column (the row elements are actually Java beans: each column will
show one distinct property of such a bean, see next section). You can
use any of the https://datatables.net/reference/option/columns.type[supported column types] by simply providing a
`String` or `Integer` based column.

==== Table rows content

Additionally, a table model class provides the content of the rows. This `getRows()` method
will be invoked asynchronously using an Ajax call. Typically, this method simply returns a list of Java Bean instances,
that provide the properties of each column (see previous section). These objects will be converted automatically
to an array of JSON objects, the basic data structure required for the DataTables API.
You will find a fully working example table model
implementation in the Git repository of the forensics plugin in the class
https://github.com/jenkinsci/forensics-api-plugin/blob/plugin-util/src/main/java/io/jenkins/plugins/forensics/miner/ForensicsTableModel.java[ForensicsTableModel].

In order to use such a table in your plugin view you need to create the table in the associated
Jelly file using the new `table` tag:

[source,xml]
.index.jelly
----

[...]

<1>
[...]

----
<1> replace `id` with the id of your table

The only parameter you need to provide for the table is the model -- it is typically part of the corresponding
Jenkins view model class (this object is referenced with `+${it}+` in the view).
In order to connect the corresponding Jenkins view model class with the table, the view model class needs to
implement the `AsyncTableContentProvider` interface. Or even simpler, let your view model class derive from
`DefaultAsyncTableContentProvider`. This relationship is required, so that Jenkins can automatically create
and bind a proxy for the Ajax calls that will automatically fill the table content after the HTML page has been created.

If we put all those pieces together, we are required to define a model similar to the model of the Forensics plugin,
that is shown in <>.

[#jenkins-view-model]
.Jenkins reporter design - high level view of the model for reporter plugins
image::forensics-view-model.png[Forensics view model]

As already described in <> the plugin needs to attach a `BuildAction` to each build. The
Forensics plugin attaches a `ForensicBuildAction` to the build. This action stores a `RepositoryStatistics` instance,
that contains the repository results for a given build. This action delegates all Stapler requests to a new
https://stapler.kohsuke.org/apidocs/org/kohsuke/stapler/StaplerProxy.html[Stapler proxy instance] so we can keep the
action clean of user interface code. This `ForensicsViewModel` class then acts as view model that provides the server
side model for the corresponding Jelly view given by the file `index.jelly`.

While this approach looks quite complex at a first view, you will see that the actual implementation part
is quite small. Most of the boilerplate code is already provided by the base classes and you need to implement
only a few methods. Using this concept also provides some additional features, that are part of the DataTables plugin:

- Ordering of columns is persisted automatically in the browser local storage.
- Paging size is persisted automatically in the browser local storage.
- The Ajax calls are actually invoked only if a table will become visible. So if you have
several tables hidden in tabs then the content will be loaded on demand only, reducing the amount of data
to be transferred.
- There is an option available to provide an additional details row that can be expanded with a + symbol,
see https://github.com/jenkinsci/warnings-ng-plugin/blob/master/doc/images/details.png[warnings plugin table] for details.

You can find several examples of Jenkins views that use jQuery in the
https://github.com/jenkinsci/warnings-ng-plugin[Warnings Next Generation plugin]
and in the https://github.com/jenkinsci/forensics-api-plugin[Forensics plugin].