Support

Lorem ipsum dolor sit amet:

24h / 365days

We offer support for our customers

Mon - Fri 8:00am - 5:00pm (GMT +1)

Get in touch

Cybersteel Inc.
376-293 City Road, Suite 600
San Francisco, CA 94102

Have any questions?
+44 1234 567 890

Drop us a line
info@yourdomain.com

About us

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.

Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec.

Theming — Adapting ReportServer's UI

With ReportServer 3.0 Enterprise Edition we have added capabilities to style the user interface to allow to adapt the look and feel to match your corporate identity. In this tutorial we want to show how to develop a new theme and provide some helpers that make theme development easier.

The Configuration File theme.cf

The ReportServer theme is controlled via the configuration file /etc/ui/theme.cf which in its basic form looks something like:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <theme type="default">

    <logo>
     <!-- define which logos to use -->
    </logo>

    <colors>
     <!-- define names for colors to be used -->
    </colors>

    <colorMapping>
     <!-- define mapping of colors to elements -->
    </colorMapping>

    <css>
     <!-- define additional css rules -->
    </css>

  </theme>
</configuration>

The <theme> element has a single attribute type which controls the ReportServer base theme that is loaded. Currently two base themes are available which are called:

default
The standard ReportServer theme.
borders
The standard theme with some additional borders.

 

The <logo> tags allow to define the logos that are used for the login screen, the logo on the top left of the module bar as well as a logo to be used in the report documentation that is displayed in the TeamSpace. Let's consider the following directive:

<logo>
   <login>
	  <html><![CDATA[<b>THE LOGIN LOGO</b>]]></html>
 	  <width>200px</width>
   </login>
   <header>
       <html><![CDATA[<b>THE HEADER LOGO</b>]]></html>
 	  <width>185px</width>
   </header>
   <report>Some URI pointing to a Logo to be used in the report documentation</report>
 </logo>

The first directive (logo.login) allows to specify an HTML snippet to be used on the login page. The width defines the width for the resulting html element. The header directive, on the other hand, controls the logo in the top left corner after login. Finally, the <report> tag can contain a URI that points to an image to be used within the report documentation.

Remember that when changing the config you need to issue the config reload command on the terminal (press CTRL+ALT+T to open the terminal) for the changes to take effect.

The <colors> and <colorMapping> tags make up the main part of a new theme. Here you can define colors (within the <colors> tag) and then assign these to various elements (within the <colorMapping> tag). A simple color definition could be

<color name="white" color="#FFFFFF"/>

This could then be assigned to the background via

<map useFor="body.bg" colorRef="white"/>

which assigns the color white to any element that uses body.bg as its color. The resulting theme.cf would then be:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <theme type="default">

    <logo>
     <!-- define which logos to use -->
    </logo>

    <colors>
     <!-- define names for colors to be used -->
     <color name="white" color="#FFFFFF"/>
    </colors>

    <colorMapping>
     <!-- define mapping of colors to elements -->
     <map useFor="body.bg" colorRef="white"/>
    </colorMapping>

    <css>
     <!-- define additional css rules -->
    </css>

  </theme>
</configuration>

Besides defining a color mapping by referencing a previously defined color, you can also directly specify a color via the color attribute. A second alternative is to set the mapping of one element group to follow another element group. For this use the sameAs attribute.

<colorMapping>
 <!-- define mapping of colors to elements -->
 <map useFor="body.bg" colorRef="white"/>
 <map useFor="tbar.btn.bg" sameAs="body.bg"/>
 <map useFor="terminal.text" color="#00B000"/>
</colorMapping>

If we can change the background color via assigning a custom color to body.bg this immediately raises the question, which element groups can we assign colors to? To get a list of the currently available element groups, you can look through ReportServer's css (and scan for css comments /*col:NAME*/) or use the following script:

import net.datenwerke.gf.service.theme.ThemeService

new TreeMap(GLOBALS.getInstance(ThemeService).colorMap).each{ k,v ->
  tout.println "$k: $v"
}

null

The script is available here.

Currently, this would tell us that the following groups are available (here with an added description):

Element Group

Color

Color Code

Description

bg

 

#B8BDC0

The background

text

 

#000000

Text when on background (bg)

bg.light

 

#FFFFFF

Light variant of background. For example used as background of panels

light.text

 

#000000

Text on light background

bg.shaded

 

#EEEEEE

A shaded variant of the background. Used, for example, as the background for toolbars

shaded.text

 

#666666

Text on shaded background

bg.dark

 

#6D708B

A darker variant of the background color

border.light

 

#B8BDC0

A color used for (thin) borders on light background

header.bg

 

#132834

The background of the top module bar (the header)

header.text.active

 

#FFFFFF

Text color of active modules and logo

header.text.inactive

 

#B8BDC0

Text color of inactive modules

header.text.right

 

#B8BDC0

Text color of user name and profile

hl.dark.bg

 

#3E4059

A dark highlight color

hl.dark.text

 

#FFFFFF

Text on the dark highlight

hl.light.bg

 

#DFE0EB

A lighter highlight color.

hl.light.text

 

#000000

Text on the lighter highlight color.

tbar.btn.bg

 

#B8BDC0

Background color of buttons in toolbars.

terminal.bg

 

#000000

Background of the terminal.

terminal.hl.bg

 

#6D708B

highlighted background of the terminal

terminal.link

 

#FFFFFF

Links on the terminal

terminal.text

 

#00B000

Standard text on the terminal

We have tried to group together elements with a similar exposure to make theming easier. At the extreme we could have given a name to every element, which, while yielding complete flexibility, would make theming much harder. However, we'd be happy to receive feedback if the above grouping causes you problems. Note that even though our grouping is not too granular, you can easily dive into the css and overwrite the styles of any specific element.

This is what the last part of the config is for. If you are not familiar with CSS, simply skip the following paragraphs.

The <css> tags enclose any additional styles that you might want to add. These are added at the very end, thus allowing you to overwrite each and every single element if you wish. Consider, for example, the teamspace grid. Here, the grid header is using the dark highlight color. The CSS from the ReportServer's default stylesheet is:

.rs-teamspace-list .rs-grid-head {
  border: none !important;
  background: none repeat scroll 0 0 #3E4059 /*col:hl.dark.bg*/ !important;
}

.rs-teamspace-list .rs-grid-head td{
  border-bottom: none !important;
  border-color: #FFFFFF /*col:hl.dark.text*/ !important;
  color: #FFFFFF /*col:hl.dark.text*/ !important;
}

If we instead wanted to use a shaded background, we could add the following directive to the theme.cf config file

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <theme type="default">

    <logo>
     <!-- define which logos to use -->
    </logo>

    <colors>
     <!-- define names for colors to be used -->
     <color name="white" color="#FFFFFF"/>
    </colors>

    <colorMapping>
     <!-- define mapping of colors to elements -->
     <map useFor="body.bg" colorRef="white"/>
    </colorMapping>

    <css>
     <!-- define additional css rules -->
     .rs-teamspace-list .rs-grid-head {
	    background: none repeat scroll 0 0 #EEEEEE /*col:bg.shaded*/ !important;
     }

     .rs-teamspace-list .rs-grid-head td{
	    border-bottom: none !important;
	    border-color: #666666 /*col:shaded.text*/ !important;
	    color: #666666 /*col:shaded.text*/ !important;
     }
    </css>

  </theme>
</configuration>

There is one thing to note. In the above above directive the css comment /*col:NAME*/ denotes a marker for ReportServer what color to choose. If present and the config file contains a custom color for bg.shaded (or shaded.text) then ReportServer would also there overwrite the color. If you want to fix the color, simply remove the CSS comment.

So much for the config file. In theory, you can now start theming. However, we can make our lives even easier with a bit of scripting.

Automatic Reload of Config File

When changing the configuration, the changes are only picked up, after we issue a config reload on the terminal. In the following we will write little script that will do this automatically. For this, we will listen to change events on files and if we detect a change on file theme.cf then we'll trigger a reload of the config file. Let's have a look at the script (for an introduction to scripting see the Administration and Script guides.

import net.datenwerke.rs.fileserver.service.fileserver.entities.FileServerFile
import net.datenwerke.security.service.eventlogger.jpa.MergeEntityEvent
import net.datenwerke.rs.utils.eventbus.EventHandler
import net.datenwerke.rs.utils.config.ConfigService

def HANDLER_NAME = "FORCE_THEME_RELOAD_HANDLER"

def configServiceProvider = GLOBALS.getProvider(ConfigService.class)

def callback = [
   handle: { e ->
	  if(null == e || ! (e instanceof MergeEntityEvent))
		 return
	  def file = e.getObject();
	  if(! "theme.cf".equals(file.getName()))
		 return

	  configServiceProvider.get().clearCache("ui/theme.cf")
   }
] as EventHandler

GLOBALS.services.callbackRegistry.attachObjectEventHandler(HANDLER_NAME, MergeEntityEvent, FileServerFile, callback)

We are interested in change events on files (internally represented by net.datenwerke.rs.fileserver.­service.­fileserver.entities.FileServerFile objects). For this, we use the callbackRegistry in line 22 to attach an ObjectEventHandler for so called MergeEntityEvents (represented by class MergeEntityEvent.class).

ReportServer will throw events whenever an object is changed, and the above registration ensures that our script is called whenever an object of type FileServerFile is merged (i.e., changed). Now the callback itself implements the single method handle which takes one parameter, the event which should be of type MergeEntityEvent (as we only registered for these). Then in the remainder (lines 14 to 18) we simply check if the merged file is called theme.cf and if so we ask the ConfigService (loaded in line 8) to clear the cache for the theme config.

When registering to receive object events you need to ensure, that your code does not throw any exceptions, as these are executed within ReportServer's main thread and an error in this case would interrupt the storage of the changed file.

Now, if you execute the script then you will notice that after changing the configuration it is sufficient to reload the browser. The changes are then directly picked up and the new theme is loaded.

This already makes theme development a few clicks faster. In the next section we introduce one more helper, to make it a blast.

Reloading new Theme without Reloading Browser

Having to reload the browser is a bit tedious, so in this final part we are going to add a button to the toolbar on the theme.cf config file which instantly reloads the theme. Following is the completed script:

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

def service = GLOBALS.services['clientExtensionService']

def entry = new AddToolbarEntryExtension()
entry.setLabel("Reload theme")
entry.setIcon("refresh")
entry.setToolbarName("fileserver:admin:view:toolbar")
entry.setJavaScript("""
	\$wnd.\$("#rs-the-theme").remove();
	\$wnd.\$('head').append( \$wnd.\$('<link id="rs-the-theme" rel="stylesheet" type="text/css" />').attr('href', 'reportserver/rstheme?' + Math.random() ) );
""")

entry.addDisplayCondition(
   new DisplayCondition("path", "/fileserver/etc/ui/theme.cf")
)

service.addToolbarEntry(entry)

The script uses the ClientExtensionService (loaded in line 3) which allows to add buttons to various toolbars, or menus. In our case, we want to add a button to the toolbar in the FileServer when the theme.cf config file is active. For this we create an AddToolbarEntryExtension (lines 5 to 12) object which we give a label and an icon (choose any Font Awesome icon).

In line 8 we tell the extension that it should apply to the toolbar identified by fileserver:admin:view:toolbar (the file server's toolbar). Without any additional conditions, the button would now appear for every object in the toolbar. Thus, to only show it on file theme.cf we add a display condition and specify the specific path (lines 14-16).

The actual work (replacing the theme) is done when pressing the button and for this we use a little bit of javascript which we add to the entry in lines 10 and eleven. ReportServer's CSS is loaded into a link tag with the id rs-the-theme. So what we need is to remove it, and replace it with a fresh tag. For this we use jQuery. Removing the tag is done by

$("#rs-the-theme").remove();

This is what we do in line 10, or almost. The reason why the above does not work directly is that ReportServer is written in GWT and the javascript is run within the GWT context (i.e., a nested frame). Thus, to access the actual context and its window object we use the variable $wnd which is provided by GWT for this purpose, making the call.

$wnd.$("#rs-the-theme").remove();

Now noticing that $ is a special instruction in groovy strings, we need to escape the $-signs.

In line 11 we add a fresh link tag to the head element which reloads the theme. And with this we are at the end of this tutorial.

Happy Theming

Zurück

InfoFabrik GmbH

Wir wollen, dass alle Unternehmen, Institutionen und Organisationen, die Daten auswerten, selbständig und zeitnah genau die Informationen erhalten, die sie für ein erfolgreiches Arbeiten benötigen.

InfoFabrik GmbH
Klingholzstr. 7
65189 Wiesbaden
Germany

+49 (0) 611 580 66 25

Kontaktieren Sie uns

Was ist die Summe aus 2 und 1?
Copyright 2007 - 2024 InfoFabrik GmbH. All Rights Reserved.

Auf unserer Website setzen wir Cookies und andere Technologien ein. Während einige davon essenziell sind, dienen andere dazu, die Website zu verbessern und den Erfolg unserer Kampagnen zu bewerten. Bei der Nutzung unserer Website werden Daten verarbeitet, um Anzeigen und Inhalte zu messen. Weitere Informationen dazu finden Sie in unserer Datenschutzerklärung. Sie haben jederzeit die Möglichkeit, Ihre Einstellungen anzupassen oder zu widerrufen.

Datenschutzerklärung Impressum
You are using an outdated browser. The website may not be displayed correctly. Close