RAD Table walker

For a project I received some very unclear description for a change. After a conversation I came up with the suggestion to rebuild the UI and present a Bootstrap table with add and delete buttons. Something what developers would call a table walker.

So how did I do this?

First I had to extend the Model object of my MVC model. The table repeats rows with persons details so I added:

The Person class is simplified as followed:

On my model object I also added getters and setters and and an add method:

Then I had to build the table with the following important elements:

  • a repeat control to represent my arraylist of Person objects
  • input fields bounded to the Person name and email
  • a button for each row to remove the Person from the arraylist
  • a button to display a new blank row to register a new Person

The code is not that long or complicated. I highlighted the important parts with bleeding yellow:

In the next phase I decided to replace the input field the name field with namespickers (by first name or by last name) wrapped as Bootstrap field add-ons. Here is the rough code:

This all resulted in a nice BS table with add / remove buttons:

Now I am just waiting for customer approval. That is mostly the longest part in Rapid Application Design.

Data for Bootstrap Treeview from a Notes View?

In a modernization project (increase of browser compatibility) I needed to find a solution for a list of links, categorized and sorted like a Notes View.

Since I already use Bootstrap as CSS framework I decided to check the following Bootstrap Treeview project: https://github.com/jonmiles/bootstrap-treeview .  I was satisfied with the following example(s):

treeview_ex.png

The initialisation is pretty simple:

snipp01

Now I just needed to set up a REST service to provide me the data. The service is setup on an XPage and bounded to a Java class:

snipp02

The Java class I will reuse for providing multiple data streams so it detects the different method parameters:

snipp03

As mentioned the data for the list comes from a Notes View. As you all know views entries have different characteristics which I have to bear in mind:

  • Documents can land anywhere in the view since it is categorized on a text field where the multiple levels can set individually eg Europe\\Sweden\\Stockholm or Afrika\\Johannesburg.
  • The view also holds links for other menus organized under a category so I decided to us a viewnavigator and start collecting data from a specific category.
  • For each entry in the view I have to check what type it is: category, document or total. The last one is not of my interest so I have to skip if that option occurs.
  • The columnindentlevel tells me all about where I am in the view in comparison with the columnindentlevel of the previous entry. Here are the scenarios:

// case 1: current indent level < columnindentlevel
// -> new category, propobably start situation
// case 2: current indent level = column indentlevel
// -> new category (sibling) but close the previous
// one first (just one level)
// case 3: current indent level > column indent
// level -> new category but closes the previous
// one(s) first. how many depends on difference curr
// and column level

Ofcourse categories behave different that documents.

So here is the code:

serv01.PNG
serv02
serv03.PNG

Some notes:

  • I have set the header of the REST service to text/html and the plugin needs a JavaScript object. Therefor capture my data response in an eval() method.
  • A target attribute is not provided by the plugin, so I add one myself. Categories have the # as href so based on that info I include a target attribute or not. I do this via a function:
snipp04
  • If the treeview is collapsed there is no anchor element for underlying list-items so you cannot add the target for all links.
  • Also when collapsing and expanding a category the added target attributes are gone. So for opening of every category you need to re-apply the href attribute for underlying anchors.
  • A category can be opened via a ‘twistie’ image or the text link so we need to register an action on these onclick events
snipp05
snipp06

The result is a nice looking ‘Notes View data-driven’ treeview with Bootstrap styling:

snipp07

Happy coding ūüôā

PS. I noticed I have a lot of unused local variables in my code, you may clean that up ūüôā

Workaround for updating the styleClass property of a button when using BS theme

In my application I am using the Bootstrap theme that comes with the extension library. In the application I have a button with which I want to enable/disable the appearance of the debugtoolbar plugin for the end-user so it will be easier to handle incident reports when they should occur.

So in my application layout control I added the toolbar and compute the appearance:

debuglayout

Now somewhere in my application I have in a dialog a button to show/hide the debug toolbar:

debugBtn In the browser it looks as followed:

debugDlg

At first when I pressed the button the styleClass would update ONLY when I totally refreshed the page which was undesired.

The trick here is to disable the theme for the button:

debugTheme

I then have to surround the button with additional HTML span element:

<span class=”btn-group”><xp:button…/></span>

As a result the button changes styleClass correctly:

debugSwinging.JPG

Want to know more about XPages dev item? Just drop a question below…

A generic approach to display Notes data via a Bootstrap table

This week I became inspired by a question I noticed on Stackoverflow regarding collecting values from Java objects.

For a project we were discussing what to use for display “Notes View data”:

  • jQuery DataTables plugin and use a customRestService via a Java class as data provider for the JSON.
  • a Repeat control and display an Arraylist of Java objects.

Some of the participants liked the jQuery approach because it provides a lot of functionality out of the box (sorting, search, responsiveness,…) and their lack in knowledge regarding Java.

Others were questioning of the Repeat control approach would be flexible enough so we could display easy different sets of data with different number of columns.

So… to the drawing board.

Mostly in Notes views (e.g. via the View Panel control) one column serves as link (often the first) and all others just display data of all kind. In the DataTables plugin the display is flexible because you can define a custom render function for each column which is great. So you could display a button that will call a dialog to interact with the underlying document for example. However this custom render definition resides in a CSJS library so becomes part of the design.

I had already a custom control that could consume properties for the data and how to set a fixed set of columns. So the last part I needed to make flexible.

Because I have an arraylist of Java objects as source for my Repeat control I need to access the fields “on the fly” when rendering the column values. This turned out to be quiet simple because the fields are already in my Java object.

In my approach I provide the columns via a JSON object that could look as followed:

dyntable00

 

And for my columns I repeat it and collect the value from my underlying Java object:

dyntable01

Note: my code is not final, I would to define more types of data and the option to provide a custom render function for each column. So far I only have computation for string and date fields.

I also applied some basic functionality as Pager controls (top + bottom), a Page Sizer control, icon display and row numbering.

Here is what a result might look like:

dyntable001

Nothing special but now now I have just one custom control to display 80% of my tables/views.

Here are the GIST files for the custom control and its configuration xml file.

IBM Champion Nomination

Is this blog-article useful to you? Perhaps you can nominate me as IBM Champion.

XPages sufficient for line of business type of applications?

Hi there, currently I am following another Angular course since it seems to have become the leading development framework at work. So back to learning all the rules within Angular.

At the moment I am modernizing a Domino application with the help of XPages which:

  1. Implements Model-View-Controller architecture, mostly inspired by the guys at Pipelia since IBM never told us to do so.
  2. Is written in Java to support the MVC architecture and to have close integration with XPages runtime.
  3. Is using Expression Language wherever possible to avoid usage of SSJS.
  4. Uses the lifecycle of JSF in XPages at the max.
  5. To cover support for different devices I am using Bootstrap as front-end framework. So I miss some native behavior which I do not tend to cover-up.

So far so good and I think I have come quiet long in my project so I still dare to call it rapid application development.

The code-base has been reduced dramatically and all exotic upcoming JavaScript libraries from the early 2000 I have been able to replace with just XPages.¬†With my latent UX skills and extending the out of the box Bootstrap I might now even call this application ‘sexy’ ūüôā

I know I haven’t touched many areas discussed in the XPages community such as:

  • Websockets (I do not see a use-case yet).
  • Writing Java servlets (please pass me a demo NSF).
  • Watson services (cloud is still a sensitive topic).
  • set up micro-services with smartNSF and consume them in my Java code with an mapper library (requires changes in the environment).
  • Integration with IBM Connections.
  • Redefining my data with the help of a Graph DB.

Either I see little usage, it is not possible or there is no-one to guide me (the information is certainly not provided by the vendor).

So now back to Angular. Learning all these rules, technologies and new tools setup I was wondering what new technical options this framework will bring me at work. Reflecting on the type of customer-orders I receive I am wondering:

Is XPages not sufficient for most of your line of business apps?

Perhaps you have a though about this?

Happy development & enjoy your summer ūüôā

Nice reversible cards in a IBM Verse style

In an application I am displaying objects with cards. Because the type of objects may differ in type and amount of data (text, images, tables, dates) the cards to display them differ.

Some cards have interaction (popup, dialogs, reversible) and some are just static. In this post I will discuss the reversible card type.

The reversible card has as features:

  • a front card with a folded corner, if you move over the fold an info icon appears which you can¬†click to see the card’s back.
  • when you flip over to the back or front it is all nicely animated.
  • on the back of the card there is another icon to switch back to the card’s front.

The purpose of this reversible card is to save space in my UI, and to provide layout for secondary information, which is more important if you want to look at more detailed information.

It could also be a placeholder for data that, when placed in the front of the card, ask for too much landscape (e.g. a chart).

Things become much clearer with images so here are a few:

card-default

Image: Default presentation.

card-mouse-over-fold

Image: Expand folding (animation) when mouse-over.

card-flipped

Image: animation when flipping over a card.

card-back

Image: the back of the card.

I use the cards within a repeat control and with Bootstrap they align nicely and are responsive:

cards

I have no idea when Bootstrap 4 will be released with it’s card component but according to my experience cards are … less useful without interaction.

I made a small video to demonstrate the reversible cards feature:

If you want to implement the card yourself here is the code:

card-code

Most of the chemistry is performed with CSS so you also want that:

body{
padding:20px;
}

.flip {
-webkit-perspective: 800;
perspective: 800;
position: relative;
text-align: left;
min-height:200px;
margin-bottom:20px;
}

.flipped {
height: 100%;
background-color:#efefef;
-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
}

.card {
height: 100%;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
transform-style: preserve-3d;
transition: 0.5s;
}

.card .face {
-webkit-backface-visibility: hidden ;
backface-visibility: hidden ;
z-index: 2;
}

.front {
/*position: relative;*/
background-color: #FFF;

height:200px;
position: absolute;
width: 100%;
z-index: 1;
border: 1px solid #e3e3e3;
box-shadow: 5px 7px rgba(0, 0, 0, 0.15);
transition: background 0.4s ease;
}

.front-content, .back-content {
padding: 20px;
}
.front-content:before {
content:””;
width: 80px;
height: 80px;
float: right;
}
.corner-tip:before, .corner-tip:after {
background-color: #FFF;
position: absolute;
display: block;
z-index: 2;
border-top-right-radius: 60%;
width: 50%;
height: 50%;
content: “”;
}
.corner-tip:before {
right: 100%;
top: 0%;
background: -webkit-radial-gradient(-180% 200%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
.front:hover .corner-tip:before {
border-right: solid 1px #fff;
}
.front div.corner:hover .corner-tip:before {
border-right: solid 2px #fff;
}
.corner-tip:after {
top: 100%;
right: 0%;
background: -webkit-radial-gradient(-250% 320%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
.front:hover .corner-tip:after {
border-top: solid 1px #fff;
}
.front div.corner:hover .corner-tip:after {
border-top: solid 2px #fff;
}
.corner { /* edit these sizes for the default revealing corner size */
height: 20px;
width: 20px;
right: 0;
top: 0;
position: absolute;
overflow: visible;
}
.front:hover .corner { /* edit corner size (First animation, when the whole page is rollovered) */
height: 30px;
width: 30px;
}
.front div.corner:hover { /* edit corner size (Second animation, when the corner itself is rollovered) */
height: 50px;
width: 50px;
}
.corner:before {
position: absolute;
top: 0;
right: 0;
content: “”;
display: block;
width: 133%;
height: 133%;
}
.corner-contents:after {
position: absolute;
top: 0;
right: 0;
content: “”;
background: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0) 37%, #DDD 62%, rgba(230, 230, 230, 0.1) 64%, rgba(255, 255, 255, 0) 67%), -webkit-radial-gradient(-50% 150%, circle, transparent 74%, rgba(0, 0, 0, 0.2) 74%, transparent 81%);
display: block;
width: 133%;
height: 133%;
}
.corner-tip {
position: absolute;
top: 0;
right: 0;
content: “”;
background: -webkit-linear-gradient(45deg, #ddd 17%, #dfdfdf 18%, #f5f5f5 30%, #f8f8f8 34%, #eee 39%, rgba(200,200,200,0) 41%);
display: block;
width: 100%;
height: 100%;
}
.corner-button {
position: absolute;
top: 0;
right: 0;
color: #fff;
text-align: center;
padding:5px;
display: inline-block;
font-size: 1.6em;
color:black;
}
.corner-contents {
width: 125%;
position: absolute;
display: block;
overflow: hidden;
-webkit-mask: -webkit-linear-gradient(45deg, transparent 49%, #000 53%);
top: 0;
right: 0;
height: 125%;
}
._corner-contents:before {
content: “”;
position: absolute;
top: 0;
right: 0;
content: “”;
display: block;
width: 100%;
height: 100%;
background-color: #eeeef4; /* Match this background color to #fpc_effect-back */
}
.corner, .corner-contents, .corner-tip {
-webkit-transition-property: all;
-webkit-transition-duration: .3s;
-webkit-transition-timing-function: cubic-bezier(0, 0.35, .5, 1.7);
}

.back {
height:200px;
width: 100%;

-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
border: 1px solid #e3e3e3;
box-shadow: 5px 7px rgba(0, 0, 0, 0.15);
transition: background 0.4s ease;
}

.imgThumb{
width:66px;
height:66px;
}

.card blockquote {
border-left: none;
margin: 0;
}

.card blockquote img {
margin-bottom: 10px;
}

.card blockquote p:before {
content: “\f10d”;
font-family: ‘Fontawesome’;
float: left;
margin-right: 10px;
}

Okay, you are now all powered to impress your customers. Happy development ūüôā

Bootstrap Greenhouse

I collected some code examples for plugins to Bootstrap in XPages in a GitHub project so I have them for convenience stored in one place.

bootstrap-greenhouse

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !

I Like Bubble Commenting

Strange subject title isn’t?

I have created a repository of my bubble/social speech layout, so if you want to have a closer look and implement it yourself then you are free to go.

I updated the @mention implementation so you get a nice icon in front of the name:

mention20

In order to have icons I updated my LotusScript agent to add a URL to an image in the PhotoURL field of the Person form in the FakeNames.nsf. For now I stored the icons in the NSF but in case you have a directory you use the reference to images from there.

I have also added an updated version to Like/Unlike comments, in stead of SSJS now most of the logic resides in the LikeController class. When you hover over the icon you get a list presented with people who have liked the comment.

likes_hover_icon

Ofcourse nothing is stress-tested but I have not seen major issues so far. I hope you like it and get inspired to modernize your IBM Notes applications !

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !

A modern commenting view in XPages

Introduction

In the old days you a typical commenting feature was something with a form and a view. Typically you could read a list of comments in a historical (flat) order and on the bottom you had the form to enter your comment. Something like in the IBM Domino blog template.

domino-blog

With the rise of social and mobile it became more important to be able to comment-only so the form moved to the top and the list of comments became sorted in the opposite order (Youtube).

Discussions are still displayed in a thread but since threads are less friendly on a mobile device a more what’app like chat display.¬†But these are more instant messaging apps, similar to Slack or IBM’s upcoming Toscana.

slack

My idea: welcome to the bubble

So what can/should we do to modernize the display of the comment feature in our Notes/XPages application?

Well mainly we still have a top level object (TLO) where people comment on. To stimulate people to comment the form should be close to this TLO. We can promote the interaction between a user and others and provide some form of “bubble speech” experience and (ofcourse) the option to “like” a comment.

That would bring us to something more like this:

social_comment

 

Notice on the left you see the comments I have made and on the right comments made by others. The latest comment is displayed first and mines are a bit more outstanding using a background-color.

Now how it’s made

To come to this solutions I am using the following technologies:

  • XPages
  • Java
  • SSJS
  • Bootstrap
  • PrettyTime
  • CSS
  • JavaScript / mention JS

Note that in a previous post I described how to add @mention autocomplete like Facebook, Twitter & Google+ to your XPages app. So I will not discuss in this post how to build the form to comment.

Here is a general outline of what we are going to build:

outline

Step 1 – basic structure; a repeater with a panel

step01

First I have a repeat control which is bound to an ArrayList containing JsonObjects. This approach you can find in my Bildr project on OpenNTF (shameless plug).

I also added an infinite scroll function. You can read about how to set that up in this post.

The panel has a computed styleclass. The style defintion “right” does nothing more than a¬† text-align: right. This makes sure the text in the content is … aligned right.

Step 2 – adding a user icon

Humans are visually oriented and idle so nothing wrong making our display attractive with a user icon.

step02

In this example I am just displaying some random icons, but if you have a corporate directory with user profiles containing icons you should embed them here.

The pull-left and pull-right classes are from Bootstrap. My comments are pulled to the left, comments from others to the right.

Step 3 – the media body

Next item that we add is a div with a media-body class. It contains out of 2 sections: the content of the comment (text written) and some meta-data (date, author). I also added a “like” link which is inspired by Thomas Adrian’s Intrapages app also available on OpenNTF.

step03

(Guess I don’t need the attributes here…). Here is the part of the meta-data:

step03b

First I display the Author name, only for comments written by others. In order to make the date more human friendly to read I am using PrettyTime. In the past I have blogged about how to use it.

For the remove link I am using the userbean to check if I can delete documents in the database and if the comment is mine: (@UserName() == obj.From) && (userBean.canDeleteDocs == true)

For the event I check and ask if I am sure that I want to remove the entry and then I simply remove it by UNID:

step03c

For the “like” button I would like to point to Adrian’s example in his Intrapages project. I made however the exeption to store the likes in a separate document, so not in the comment. By this way I can tighten my security model. Everybody has the role of [liker] and author access. So everybody can update a like document and not the original comment document.

The like function uses the cookie management principles described here. It stores the username:

userCookie = new javax.servlet.http.Cookie(“userid”, @UserName());

I have set the duration of the cookie as long as the session is active:

//Cookie.setMaxAge(-1) will make the cookie expire after the browser is closed
userCookie.setMaxAge(-1);

But beware that the cookie still exists when users logout and login with a different username-password combination !!

So I have a counter for the number of likes, and depending on my activity I have a like or unlike link.

Ready! Some CSS whistles

After we have added some more (basic) CSS we are done! As a result we have created something much more modern that the old school comments display as we know from the IBM Domino Blog template.

If you are interested and want to receive the details of this setup I welcome you to send me a message and we can exchange code.

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !