Make It Red and Uppercase with Nuxeo Studio


Mon 06 May 2013 By Thibaud Arguillere

Building a wonderful content-centric application with a perfect taxonomy, with damn smart workflows, with incredible automation chains, etc. is great, sure. Still. You still need to paint it, if you see what I mean.

Nuxeo Studio lets you easily define the main branding of your application: login screen, colors used for text, background, links, … It is documented here. That said, you also often need to be more context-specific. For example, you may want to display a text widget in red so the user knows it is an important part of the layout. Or you may also want to force data entry with upper case letters for example.

Let's take the following example: A workflow…

blogta2-01-Workflow

… has a "name" workflow variable. The form of its "First task" node displays this variable in a text widget…

blogta2-02-DropField

… and you want it to be displayed in red.

So, you set its "Style class" property to "doItRed"…

blogta2-03-StetStyleClass

…you save, and in the branding you create the doItRed style:

bogta2-00-Red-StyleInBranding

Then, you test your work(1).

. . . [here, I'm waiting while you are testing] . . .

You probably noticed something very unfortunate happened: It does not work as expected. The value we entered in the "Name" field is displayed in black. We want it red, right? So, how can we do this? How can we change the style of a widget?

Before explaining how you can customize this widget, I'd like to say you could have used one of the predefined classes provided by Nuxeo (and explained in the Nuxeo UI Style Guide.) For example, by using "warning" or "error", our text would have been displayed in red. But here, we want it red-red, so we have an example of customization that can't use a predefined class.

If you need the thing to be red now, immediately, can't wait, emergency-emergency, then you may have the idea to use !important:

.doItRed {
color:red !important;
}

And well, yes, it works. But the thing is: You don't want to use it. Really. I believe !important has been added to the specification when the CSS team was spending time in Vegas with The Hangover folks. If you start using it, you'll soon find yourself using it everywhere and at some point in a short future, nothing will work at all, your user interface will be broken. Instead of using it, it is better to understand why your style is not used. So, we remove this !important thing, save, update our project in the server and run it.

A web inspector is the perfect tool for the purpose of understanding what happened to our style. So, at runtime, we display the inspector and select our widget. The right pane clearly shows that the class has been overridden (it is in strikethrough):

blogta2-04-WebInspectorStyle

What happened here is that the default nuxeo theme, "galaxyDefaultCssNNN" (with NN being a number dynamically evaluated by the server) has been applied after our own class, hence the fact that our red color is not used.

What can we do to display our widget in red? We must (besides not using The Suffix That Must Not Be Named) use a CSS definition that will have a higher priority than the Galaxy one. Using the DOM ID of the widget would work, but it is complicated to get this ID, since it is generated at runtime (we don't know this ID at the time we are adding the class in Studio). The best solution is to define our style by using the class hierarchy that is applied to our widget:

.classOfAncestor [...] .classOfParent .classOfElement {...}

So, we take look at the web inspector and find the classes:

blogta2-05-CheckInheritance

It is good to be specific in the path and get the right ancestors. In our example, we want to apply the style only in the context of a task, so we walk the path up to "single_tasks_block". The CSS we must define is:

.single_tasks_block .dataInput .fieldColumn .doItRed {
color:red;
}

If you want to apply your red style in a wider area than a table, don't hesitate to use the framework CSS classes: .nxHeader, .nxMainContainer, .nxFooter. These classes are called in all the pages of the platform.

There is one last thing to do actually: Our doItRed class becomes a place holder that we use for the "Style class" widget property. We can leave it empty. So, here is our CSS definition in the branding:

blobta2-00-StyleInBranding

Save. Update(2). Run. Enjoy.

We can now move a step further. Because at the beginning of the article, I was talking about displaying the field in red, but also as upper case. We want every character, every key hit by the user to be displayed as upper case.

How you implement this in Nuxeo Studio depends on what you need. Either you just want to display data entry in upper case, or you want the field itself, its content, to hold only upper case letters. Just displaying uppercase is quite easy -- we add the appropriate text-transform style:

.single_tasks_block .dataInput .fieldColumn .doItRed {
color:red;
text-transform:uppercase;
}

That's all. CSS handles the conversion at runtime. I'll add that we should then rename our class, because giving useful names is useful(3). If we do rename the class, we will not forget to change the "Style class" widget property in our task form.

Also notice that it is only about how the data is displayed: CSS does not change the actual content. In our example if the user enters "john" in the name workflow variable, it will be displayed as "JOHN", but the variable itself still holds "john".

If we want the transformation to be persistent, then we have to move to something different. Here is my suggestion: To stay with the CSS transformation for the display, and to add a "Transform to Uppercase" automation chain to the workflow. In our example, we added a basic "OK" button to the "First task" form. This button does nothing but move to "Second task". We can now add an automation chain to the transition, which will be run when the user hits this "Ok" button. In the "Transitions" tab of the node properties dialog, click the "Create" button:

blogta2-06-createChain

We name the chain "upperCaseName". Our challenge is to set the name field to uppercase. It is a workflow variable. So we use the "Workflow context > Set context variable" operation chain. We can safely remove the first, default action ("Fetch > Context document") that was created by Studio because we are not - in this example - using the document.

Here is what our chain looks like:

blogta2-07-EmptyChain

The "name" field is obvious: our workflow variable's name is "name" (funny, isn't it?).

Now what should we put in the "value" field of this chain to transform the characters to uppercase? You can use here a MVEL expression. Not everything is allowed in this context, but to make a long story short, basically, everything that is put between @{ and } is evaluated as a Java expression. Some expressions are very specific to Nuxeo, but you can also use a bit of Java here. And even more interesting for us, we can use its String class. And guess what? The String class has a toUpperCase() method whose function is quite clear in my opinion. This means that when you have a string, you just have to write…

myString.toUpperCase()

…to return a capitalized string. And a hard coded expression is also valid. I mean something like…

"nuxeo studio rocks".toUpperCase()

…returns "NUXEO STUDIO ROCKS".

So basically, what we have to do now is to get the current value of the name workflow variable, and to transform it to upper case. Getting its value is done using the helper drop down menus of the expression dialog. We select "Workflow Variables" in first drop-down, then ["var"] in the second, and then we click "Insert"…

blogta2-11-Expression

…this inserts the expression:

@{WorkflowVariables["var"]}

We replace "var" with "name", since it is the name of our variable. The expression between the curly brackets is evaluated at runtime and returns a string: The characters the user entered. Because it is a string, we can call the toUpperCase() Java String method. We just need to be careful and to let the whole thing inside the curly brackets:
@{WorkflowVariables["name"].toUpperCase()}

We're done with our automation chain, which contains actually one single operation:

blogta2-12-ExpressionFinal

We save, update and run. After starting a workflow on a document, here is my first task. I entered everything in lower case, "working well". The CSS transformation displays it as we want:

blogta2-13-WorkWellTask1

Then, when I hit the "OK" button, the chain is run and "working well" is transformed using Java. So its value is now "WORKING WELL":

blogta2-14-WorkWellTask2

Isn't it wonderful that you can customize your application in such detail with Nuxeo Studio?

And don't forget to add comments in your CSS to make it readable and easy to follow for you team(5).

(1) Yes. Checking that what we do works as expected is part of our lives
(2) Update the project in the server. Something we sometimes forget. Then we wonder why our changes don't work. Come on.
(3) Yes, that's what I wrote: Useful is useful.
(4) If you are not very familiar with Java, it is not a problem at all. Finding the appropriate function requires a simple Internet search on keywords like "java upper case". You'll get an answer such as "use the toUpperCase method of the String class"
(5) Lise Kemen helped me a lot on this article. She is our CSS super specialist (see the Nuxeo UI Style Guide for example). She also she really insisted for this "comment your class" to be added. And when Lise really insists, well, you know, you just follow the orders.

Enhanced by Zemanta

Category: Product & Development
Tagged: How to, Nuxeo Studio, Workflow