Working with JSON in your XPages application – Refined view

In a previous post I wrote how you could use a Notes view as the data source for JSONObjects. In a recent project I needed to minimize the data amount to transfer so I had to exclude the fields that contain no value. Here is the @formula I can up with for the column value:

REM { Patrick Kwinten

Quick way to deliver ‘cached’ JSON objects from Notes documents

};

REM {JSONObject bricks};

jsonOpener := “{“;

jsonSeparator := “,”;

jsonClosure := “}”;

REM {String helper};

src := “\\”:”‘”:@NewLine:”\””;

dst :=  “\\\\”:”\\'”:”\\n”:”\\\””;

REM {Define which fields to exclude/include in JSON object};

REM {“Idea taken from http://www.eknori.de/2012-06-01/use-transform-to-build-json-and-consume-the-output-in-an-xagent/”};

_exclude:=”$FILE”:”$Fonts”:”form”:”$Revisions”:”ID”:”ModifiedBy”:”$TUA”;

_fld:=@Trim(@ReplaceSubstring(@DocFields;_exclude;@Nothing));

REM {Output for “custom” fields. Empty values are excluded};

_fldOutput := “”;

@For(

n := 1;

n <= @Elements(_fld);

n := n + 1;

@Do(

_fldVal := @Text ( @GetField ( _fld[n] ) );

@If(_fldVal != “” ; _fldOutput := _fldOutput + “\”” + _fld[n] + “\”:\”” + @ReplaceSubstring( _fldVal; Src; Dst )  + “\”” + @If(n != @Elements(_fld); jsonSeparator;””); “”)

)

);

REM {Prepare output};

outputStr := “”;

outputStr := outputStr + jsonOpener;

REM {Output for “default” fields};

tmpUNID:= @Text(@DocumentUniqueID);

outputStr := outputStr + “\”docUNID\”:\”” + tmpUNID  + “\”” + jsonSeparator;

outputStr := outputStr + _fldOutput;

REM {Finalize JSONObject};

outputStr := outputStr + jsonClosure;

REM {Return output};

@Return(outputStr)

As a result I have “lesser” JSON Objects in my view:

Screen Shot 2016-03-01 at 10.20.40

Born Social available on GitHub

A long, long time ago I wrote about a project to deliver small building blocks to deliver features from the IBM Connections in XPages application. The posting can be found here: https://quintessens.wordpress.com/2015/04/16/born-social-create-a-social-notes-application-from-scratch/ .

Here and then I was asked to share the project or asked about the progress but since I rarely work with the Connections  platform anymore I thought it could be helpful to upload the Born Social project on GitHub so people can make use of it if they like to.

Unfortunately in the meantime I did no hear or read so much about integration between Connections and IBM Domino so I am not sure if this is a (hot) topic anymore. My initial thought with the project was that it would be ‘cool’ to utilize data in Connections in XPages applications.

I also wrote a small document that helps you to get the application up and running and explains how to use the re-usable custom controls.

The project is available here on GitHub.

I just modernized an application

Introduction

While following the buzz from IBMConnect16 remote I have been working in spare time on my Bildr project available on OpenNTF.

This time I have been focussing on improving the UI by adding more material design principles which should make it easier to distinguish content on a page. Beside that it is just good fun to work with UI sometimes it forces you to improve the back-end logic also.

Capture02

The image above demonstrates the display of related content on a single page where a profile contains lists of related documents.

NoSQL is a party

The following image demonstrates the information (e.g. categories) abstracted from a list of documents and on the right a random selected document from that list and showing some abstracted information from that document.

Capture04

Here you can see well IBM Notes works as a nosql database where documents are loosely coupled and may contain almost anything (well I try to avoid rich text). Especially in a rapid application development paradigm I like the flexibility of nostrict data structure at the time you start developing.

I have not heard much news about NSF from IBMConnect (Solr? Graph features? Performance improvements?) to make it competitive to other nosql options (why do I not see NSF back in this list?).

I hope IBM is aware of NSF’s image problem and admits steps need to be taken to improve it.

Bluemix

I am not sure what the next step for the app will be but I haven’t tried it on Bluemix yet, which could be interesting. The XGallery demo on YouTube shows some great potential.

 

Modernizing a Notes application

Introduction

The quickest way of modernizing your application build on Notes is probably by keeping it on that sublime application platform and provide a new user-interface and updated business logic to it.

As a demonstratable example I would like to bring up my own Bildr project on OpenNTF.

A brief history

The application started initially as a web browser display only and create content via the Notes client application in the early 2000’s. From that the application was updated in a create content via the web browser too features.

Later the oneUI was implemented in a later step also utilizing the Application Layout control. With the Bootstrap4XPages plugin a responsive UI could be delivered a couple of years ago.

Nowadays the Application Layout control is no longer used but the Bootstrap responsive features and components are used further through the application.

The application still relies on XPages and Notes data (allthough used mainly in JSON format). The business logic resides mainly in Java Classes. With the separation of design and data the application could be hosted on Bluemix (not tested, please do).

Modernization

Looking back at this application story I believe the application will change also in the future (or die) perhaps a challenge could be to have the data optional in a different source (e.g. MongoDB) or exchange XPages for Angular and run it on Node.js.

So if you have experience moving data from Notes to MongoDb, applying a similar ACL and Roles security model on your application I would be happy to hear your experiences.

Or if you are still on the Notes client only level and want to bring your application to a (mobile) browser I am happy to exchange ideas with you and learn from your situation.

New release

Why am I saying this? Today I uploaded a new version on OpenNTF and for many Notes developers who a) not have taken the XPages path yet b) unfamiliar with Java and JSON the application could be a great starter example.

Lately there are not that many (new, updated) projects (applications) available at OpenNTF so the chance to find a working demo to see and understand the code and data running are a bit scarce (I am sorry).

I remember in the days of Superhuman Software a quote about Notes and collaboration was “dare to share” so I would challenge more developers to do so. We can learn a lot from examples from others and I thank those people who (still) do and from which I can learn from!

I wish you a wonderful learning experience at IBMConnect 2016!

Capture04

 

Bootstrap Pills navigation for Dynamic Content control

Introduction

Besides parameters you can include a hash (#) property in the URL in your XPages application. This “fragment identifier” is a short string of characters that refers to a resource that is subordinate to another, primary resource.

So it is mainly used to set a location anchor to a part in a page.

In this post I will show how to get value of Hash property in XPages and make a nice Bootstrap Pills navigation control for the Dynamic Content Control

XPages

In XPages you can use it within the xp:link control but the dynamic content control also makes use of it.

XSnippet Dynamic Content Control

The following XSnippet demonstrates how to set up a dynamic content control:

<?xml version="1.0" encoding="UTF-8"?>
  <xp:link escape="true" text="Load Dynamic Content Server side" id="link1">
    <xp:eventHandler event="onclick" submit="true" refreshMode="partial">
      <xp:this.action>
        <![CDATA[#{javascript:getComponent("dynC").show("key1")}]]>
      </xp:this.action>
    </xp:eventHandler>
  </xp:link>
  <xp:link escape="true" text="Load Dynamic Content Client side" id="link2">
    <xp:eventHandler event="onclick" submit="false">
      <xp:this.script><![CDATA[XSP.showContent("#{id:dynC}","key2")]]></xp:this.script>
    </xp:eventHandler>
  </xp:link>
  <xe:dynamicContent id="dynC" useHash="true">
    <xp:this.facets>
      <xp:panel xp:key="key1">Content1</xp:panel>
      <xp:panel xp:key="key2">Content2</xp:panel>
    </xp:this.facets>
  </xe:dynamicContent>
</xp:view>
With this snippet you get the following Hash set in the URL of your XPage: #content=…

Getting value of Hash property

I suggest to use one of the following 2 options to collect the value of the hash property:

  1. Use a custom function
  2. Use Dojo

The first option is another XSnippet by Thomas Adrian. The second is a suggestion by Mark Leusink to (re)use Dojo.

getHashUrlVars

Include the function in a shared CSJS library and call it via the function getHashUrlVars()["content"].

dojo.queryToObject

The dojo approach is also straightforward. Call the function dojo.queryToObject( dojo.hash() ); and then abstract the content property var active = hash[“content”];.

Pills navigation for Dynamic Content Control

Since there is no list item control in XPages it is a bit hard to set the properties via computation. However via CSJS you can manipulate the DOM a lot and add some responsiveness yourself.

The following script builds an unorderlist containing links to set a part of the Dynamic Content control as visible:

<xp:div id=”nav-pills-container”>
<ul class=”nav nav-pills”>
<li id=”Pictures” class=”dclist”>
<xp:link escape=”true” text=”Pictures” id=”link4″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Pictures”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>

<li id=”Albums” class=”dclist”>
<xp:link escape=”true” text=”Albums” id=”link1″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Albums”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>
<li id=”Profiles” class=”dclist”>
<xp:link escape=”true” text=”Profiles” id=”link2″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Profiles”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>

</ul>

The second script checks which content section is set “visible” for the Dynamic Content control via the hash property in the URL. The corresponding list item in the Pills navigation is set as active.

<xp:eventHandler event=”onClientLoad” submit=”false”>
<xp:this.script><![CDATA[function setActive(id){
$( “li.dclist” ).removeClass( “active” );
var id = “#” + id;
$(id).addClass( “active” );
}

var hash = dojo.queryToObject( dojo.hash() );
var active = hash[“content”];
setActive(active);
]]></xp:this.script>
</xp:eventHandler>

As a result I get the correct list item displayed as active for my Pills navigation:

navpills

Code

In case you want to see the code working in an example download the Bildr application on OpenNTF. There I have applied this technique for the search function.

 

Bildr 5 released on OpenNTF

Announcement

Today I released a new version of Bildr on OpenNTF ! There have been spent quiet a few long evenings coding but it was fun (I may drink at home) and interesting!

So just before the holiday season and January’s  IBM Connect buzz I thought it would be a proper moment for a release. So consider it my Xmas present to the community:-)

Modernization

I label this version 5.0 since I (almost) completely rewrote the application from scratch. Lot of the logic I have placed in Java classes and the data format is mainly JSON.

I also separated the design from the data so in principle you should be able to place the app in the IBM Bluemix environment.

Because of these decisions there is no backward compatibility so a simple replace design will not work for your existing installation.

Below you can find some screenshots of the new interface. I hope you like it.

Screenshots

startpage

uploadprofilepicture

Thank you

I would like to thank all the teachers in our community who post their presentations, code samples and answers on the platforms out there.

I have tried to post the code on Github but this failed with the Github desktop client. If some can get me started with that I will distribute the project there too.

For now:

A Merry Christmas and fortune in 2016 !

Re-Unite Gallery & FIX AMD loading for XPages

Introduction

In my previous post “Another draw (unite gallery) in the waste-basket” I wrote the complication I had with getting the Unite Gallery to work properly within XPages.

It turns out that this is related to Asynchronous module definition complications within XPages., although you do not get error messages in your web browser console.

Fixing the XPages R9 dojo define.amd problem once and for all

Marky Roden wrote a post about a solution a while ago which was inspired by a x-code snippet Ferry Kranenburg posted.

The principle is quiet simple but saves you a lot of headaches:

  • duplicates define.amd to define._amd
  • deletes define.amd
  • loads the AMD enabled jquery plugin (successfully)
  • duplicates define._amd back to define.amd
  • deletes define._amd

Using a Theme

In stead of setting the fix for individual pages I am using a Theme to fix it (since I am using a Select2 combobox in my navbar header).

amd fix

Step 1 – Adding two JS libraries to your WebContent

These files contain the same code as in the XSnippet.

Step 2 – Load your resources via a Theme design element

amd_theme

As you can see I load my JavaScript libraries who use AMD within the two previous set up libraries.

Result

As a result the buttons on the XPage containing the Unite Gallery work fine again !

Happy development =)

 

Another draw (unite gallery) in the waste-basket

Gallery galore

For an application I want to provide an image slider, in stead of the default Bootstrap carousel. I remembered a blog post of Johnny Oldenburger about Unite Gallery a while ago so I gave that a try.

Repeat and xp:image

Where Johnny demonstrated some static images I want to populate the image collection so I set up a repeat control with an xp:image control inside and calculate it’s properties.

Here is what the code looks like:

Code

The code of the XPage you can download here.

 

Code walk-through

After loading the JS resources I have a script block that build the gallery when the document is ready. The div gallery functions as container for the gallery.

Then I have a repeat control. An album object is just a Notes document that contains references to other Notes documents containing the picture files. So my Album.getPictures method returns a vector of references for which I have to make a lookup (via a Picture object) and collect some values (which size picture to use (thumbnail or original).

I separate the design from the data, so I also have to collect the location of the data db.

In the example I have two ways to define the image, one is via a xp:text control and the other is via the xp:image control. I rather prefer this last option.

Result

 

Below you can see a snippet of how the result. At first it looks nice, does’t it?unitegallery

Complications with XPages

So after I got the gallery on my XPage with dynamic content I started to notice undesired behaviour. My Bootstrap navbar links (xp:link) didn’t work anymore. Buttons on the same page stopped behaving and more.

A quick search after “Unite Gallery and XPages” lead me to some stackoverflow questions where people described similar problems.

Untill now I have not found a solution to get it working.

Lesson learned

Before implementing a plugin in XPages, do some research on possible complications.

 

 

Quick way to get dynamic (BS) list groups from Notes views

Introduction

For an app I needed lists to let users quickly to have access to a subset of documents. Bootstrap has a nice feature called List Groups which gives you a nice basic UI for unordered lists with list-items.

A list group can contain badges which I find a nice alternative for a tag cloud which to me are not very mobile friendly.

Before we get started let’s show how the end-result could look like:

list-group computed

So how do we do this in XPages & Java?

First I want to point to a snippet Oliver Busse posted about Iterating through a HashMap in a repeat control. If you use that basic principle of binding a HashMap to a Repeat Control  and use a categorized view for filling the Hashmap you are there!

Java class snippet

Below is the snippet from my Java class:

public Set<Entry<String, Integer>> categoriesMap(String viewName) throws NotesException{
HashMap<String, Integer> categories = new HashMap<String, Integer>();
Database dataDB = dao.getDatabase();
String ViewName = viewName;
ViewNavigator nav = dataDB.getView(viewName).createViewNav();
ViewEntry entry = nav.getFirst();
while (entry != null && !entry.isTotal()){
categories.put(entry.getColumnValues().firstElement().toString(), entry.getChildCount());
ViewEntry tmpentry = nav.getNextSibling(entry);
entry.recycle();
entry = tmpentry;
}
nav.recycle();
return categories.entrySet();
}

The code will run through the provided Notes view and go through the categories and places the name/label and value/totals in a Map and returns a set view of the mappings contained in this map.

Custom Control

Next step is to place the list-group code from Bootstrap in a custom control and make it dynamic by generating the list-items via a Repeat control and bind that control to my Java code:

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core”&gt;
<h2>
<xp:text
escape=”true”
id=”computedField1″
value=”#{javascript:compositeData.header}”>
</xp:text></h2>
<ul class=”list-group”>
<xp:repeat
id=”repeat1″
rows=”30″
var=”obj”
indexVar=”idx”>
<xp:this.value><![CDATA[#{javascript:var viewName = compositeData.viewName;
Picture.categoriesMap(viewName);}]]></xp:this.value>
<li class=”list-group-item”>
<span class=”badge”>
<xp:text
escape=”true”
id=”computedField2″
value=”#{javascript:obj.getValue()}”>
</xp:text>
</span>
<xp:link
escape=”true”
text=”#{javascript:obj.getKey()}”
id=”link1″>
<xp:eventHandler
event=”onclick”
submit=”true”
refreshMode=”complete”>
<xp:this.action>
<xp:openPage>
<xp:this.name><![CDATA[#{javascript:var target = compositeData.targetPage;
return target + “?filter=” + obj.getKey();}]]></xp:this.name>
</xp:openPage>
</xp:this.action></xp:eventHandler>
</xp:link>
</li>
</xp:repeat>
</ul>
</xp:view>

Properties

The custom controls takes in some properties set in the Property Definition section. Via this way I can re-use the Custom control for multiple dynamic list groups:

Conclusion

As you see, with a minimal amount of code you can create dynamic lists for your apps. In the sample above I do not handle views with more than 30 categories but I am sure you fix this yourself. Also the active class property is not implemented.

Happy development =)