8.3. ClientExtensionService

So far we have seen how to customize the output within the terminal, how to display messages in popups or execute custom JavaScript. In this section we will look at the so-called ClientExtensionService that can be accessed via the GLOBALS object. The ClientExtensionService offers methods to insert entries to various toolbars and context menus. Each new entry comes with a callback, that is, a ReportServer script that is executed when the specified entry is activated. Depending on where you added the entry your script is provided with additional information. For example, when adding an entry to the context menu in the report management view in the admin module, your script will get the id of the corresponding report object as an argument.

One thing to keep in mind when using the ClientExtensionService is that all effects are only valid as long as the current page is not refreshed. In order to install the changes permanently you should thus add the script into the onlogin.d folder.

The ClientExtensionService currently offers the following methods.

addStatusBarLabel() Allows to display info texts in the status bar.
addMenuEntry() Allows to add entries to certain context menus.
addToolbarEntry() Allows to add buttons to certain toolbars.
addReportExportOutputFormat() Allows to create custom exporters. We discuss this in detail in Chapter 11.
8.3.1. Adding Information to the Status Bar

The first method (addStatusBarLabel) allows you to add simple info texts to the status bar. The concept is best explained by a small example.

def service = GLOBALS.services['clientExtensionService']

service.addStatusBarLabel("All is fine")

As you might have guessed, the first line obtains the ClientExtensionService from the GLOBALs object. All that is left to do is to set a status update. Besides just adding text you can also call

addStatusBarLabel("All is fine", "path to some icon", true)

where the second parameter should point to an icon and the third parameter controls whether the object is added to the left or to the right (default).

You can of course access all server objects and methods within this script. E.g., the following executes a given dynamic list and prints the report name and its number of records into the status bar.

import net.datenwerke.rs.base.service.reportengines.table.entities.*
import net.datenwerke.rs.base.service.reportengines.table.*
import net.datenwerke.rs.core.service.reportmanager.*
import net.datenwerke.rs.base.service.reportengines.table.entities.TableReportVariant
import net.datenwerke.rs.core.service.reportmanager.ReportService
import net.datenwerke.rs.core.service.reportmanager.ReportExecutorService
import net.datenwerke.rs.base.service.reportengines.table.output.object.RSTableModel
import net.datenwerke.rs.core.service.reportmanager.engine.config.ReportExecutionConfig

ReportService reportService = GLOBALS.getRsService(ReportService.class)
ReportExecutorService reportExec = GLOBALS.getRsService(ReportExecutorService.class)

TableReportVariant report = reportService.getReportById(2078898)

String reportName = report.getName()

RSTableModel reportCompiled = (RSTableModel) reportExec.execute(report, "RS_TABLE", ReportExecutionConfig.EMPTY_CONFIG)

int rowCount = reportCompiled.getRowCount()
/* prepare output */
def ces = GLOBALS.services.clientExtensionService
ces.addStatusBarLabel("Info: ${reportName} - ${rowCount} rows")
8.3.2. Adding Context Menu Entries

The ClientExtensionService allows you to add menu entries to the following context menus

Module Description Menu Name
Datasource Manager The datasource manager within the admin module datasource:admin:tree:menu
Report Manager The report manager within the admin module reportmanager:admin:tree:menu
File Server The file server within the admin module fileserver:admin:tree:menu
Dadget Library The dadgetlibrary within the admin module usermanager:admin:tree:menu
User Manager The user manager within the admin module dashboard:admin:tree:menu

To add an entry to a specific menu you need to access the menu by name (we give the menu names in the above table, for example, usermanager:admin:tree:menu corresponds to the context menu within the user manager tree).

The simplest way to add a menu entry is to simply call the method addMenuEntry() from the ClientExtensionService:

public void addMenuEntry(String menuName, String entryName, String scriptLocation, String configArgument)

The method takes the menu name, a name for the entry, a location of the script that is to be called when the entry is activated, and an argument given to the script. In the following we want to add a menu to the user tree. We call our script that generates the entry adddisplayinfoentry.groovy.

def service = GLOBALS.services['clientExtensionService']

service.addMenuEntry("usermanager:admin:tree:menu", "display info", "fileserver/bin/extensions/menu/displayuserinfo.groovy", "an argument")
The script must be executed before the user tree is loaded for the first time.

If you execute the above script and navigate to the user manager in the administration module and right click on any item in the tree you will see the new entry.

display info

If you activate the entry you will see an error message, since we haven't yet created a script at location


We are now going to create this file and use the above and display a simple message outputting the object's id.

import net.datenwerke.rs.terminal.service.terminal.obj.*

def result = new CommandResult() 
def msg = new CreMessage("ID: " + context['id'] + ", args" + args)

return result

The important part here is the context object which contains a field id corresponding to the id of the object clicked upon. Besides the id, the context also contains

id The object's id.
classname The object's classname.
path The object's path.
Display Conditions

Sometimes it might be inconvenient to add the menu entry to every object in the tree. That is, maybe we want to add an entry only to user objects, but not to groups or organizational units. To have full control over how the menu item is created you can directly create an object of type AddMenuEntryExtension located in package net.datenwerke.rs.scripting.service.scripting.extensions. To better control when the entry is displayed, use DisplayConditions (located in the same package).

import net.datenwerke.rs.scripting.service.scripting.extensions.*

def service = GLOBALS.services['clientExtensionService']
def entry = new AddMenuEntryExtension()
entry.setLabel("display info")

def cond = new DisplayCondition("classname", "net.datenwerke.security.client.usermanager.dto.UserDto")

Note that the for menus you can currently only compare classnames. Also note that always the base class of the DTO is used, that is, instead of UserDtoDec you need to use UserDto.
8.3.3. Adding Toolbar Entries

Besides adding entries to context menus, you can add buttons to various toolbars, including all toolbars within the various admin modules. The mechanism is similar to the mechanism we described above. The following toolbars support the addition of custom buttons:

Module Description Menu Name
Datasource Manager The datasource manager within the admin module datasource:admin:view:toolbar
Report Manager The report manager within the admin module reportmanager:admin:view:toolbar
File Server The file server within the admin module fileserver:admin:view:toolbar
Dadget Library The dadgetlibrary within the admin module usermanager:admin:view:toolbar
User Manager The user manager within the admin module dashboard:admin:view:toolbar
Report Executor The report executor module. This includes the report execution by URL. reportexecutor:main:toolbar
Scheduler Job List The scheduler job list module. schedulerlist:main:toolbar

Similar as above you can either use helper methods within the ClientExtensionService such as

public void addToolbarEntry(String toolbarName, String entryName, String entryIcon, String scriptLocation, String arguments){

or alternatively create an object of type AddToolbarEntryExtension, also located in the package net.datenwerke.rs.scripting.service.scripting.extensions.

import net.datenwerke.rs.scripting.service.scripting.extensions.*

def service = GLOBALS.services['clientExtensionService']
def entry = new AddToolbarEntryExtension()
entry.setLabel("display info")

def cond = new DisplayCondition("classname", "net.datenwerke.security.client.usermanager.dto.decorator.UserDtoDec")

Note that with toolbar buttons you have more control over when buttons are to be displayed, as you can specify the exact type, that is, TableReportVariantDto instead of ReportVariantDto. This, for example, allows you to add a custom button only to dynamic lists, but not to jasper reports.
8.3.4. Future Additions

The possibilities offered by the ClientExtensionService are still rudimentary. We plan to extend these in future versions and are keen to hear your thoughts on what you would like to be able to do and what you are currently missing.