Slides from ICONUS 2016: XPages and Office 365 development – more familiar that you think

Here is the slide deck from my ICON US virtual presentation on XPages and Office 365 development

 

Please let me know if you have any questions ūüôā

Advertisements

Speaking at Engage: “Dev04.¬†XPages and Office 365 development ‚Äď more familiar that you think”

I am very proud to be speaking at the Engage 2016 User Group conference, in Eindhoven March 24th

Thursday, March 24 | 09:00 – 10:00 | D. Saturn

This is a very interesting session for me personally because it reflects how my job has allowed me to evolve¬†into areas of development which are not just XPages. Don’t get me wrong, I am far from done with the XPages world, but with¬†a lot of our customers having a¬†mixed Domino and Office 365 environment the past year has presented some new challenges and opportunities.

I always believe that a picture is worth more than a thousand words and in this session I will show many demonstrations of what is possible and go into some details of how O365 development and modern Domino web development are really very similar.

I look forward to seeing as many people as possible bright and early on march 24th ūüôā

Abstract

Many companies run a mixed IBM Notes and Microsoft Office 365 (O365) environment. SharePoint/Outlook and Domino should be viewed as a new opportunity to create rich and engaging user experiences. Using both IBM and Microsoft REST services as the core to the solution, this presentation will show how both technologies stacks can be integrated to maximize application functionality and present a seamless experience to the user. Mark will provide lots of demonstrations including Office Web Add-Ins, how to access O365 data from your Domino applications and many others. Come and see how your core Domino webdev skills are equally applicable to the Office 365 environment.

IBMSBT in XPages: My Communities

In this article I will describe how to display a list of “My Communities” in an XPage. To do this I will have to create an ArrayList of communities and use a repeat control in an XPage to display them.

Getting My Communities

As I showed in this previous blog post there were some interesting issues in setting up the managed beans for getting the communities out of connections/smartcloud.

But in quick review this is the code for getting my communities.

package com.xomino.sbt;

import java.util.Collection;
import javax.faces.context.FacesContext;

import com.ibm.sbt.services.client.ClientServicesException;
import com.ibm.sbt.services.client.connections.communities.Community;
import com.ibm.sbt.services.client.connections.communities.CommunityList;
import com.ibm.sbt.services.client.connections.communities.CommunityService;
import com.ibm.sbt.services.client.connections.communities.CommunityServiceException;
import com.ibm.sbt.services.endpoints.Endpoint;
import com.ibm.xsp.extlib.util.ExtLibUtil;

public class Utils {

	public static void checkAuthentication() throws ClientServicesException{
		Endpoint theEndpoint = getEndpoint();
		if (!theEndpoint.isAuthenticated()){
			theEndpoint.authenticate(true);
		}
	}

	public static Endpoint getEndpoint(){
		Endpoint endpoint = (Endpoint) ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), "smartcloud");
		return endpoint;
	}

	public static Collection<Community> getCommunities() throws CommunityServiceException{
		CommunityService svc = new CommunityService();
		CommunityList communities = svc.getMyCommunities();
		return communities;
	}
}

What is interesting is that the svc.getMyCommunities() returns a “Collection” and the code assist not only told me this, but it changed the return of the method “Collection” and added the import java.util.Collection.

So that is all well and good – but then how do I get that only my XPage?

Well I actually used the JavaDoc !
c1

So then in the XPage I used a repeat control to iterate through the “collection”

<xp:repeat id="repeat2" rows="30"
	value="#{javascript:com.xomino.sbt.Utils.getCommunities()}" var="myCommunities">
	<xp:div styleClass="readonly" disableTheme="true">
		<xp:text disableTheme="true">
		  <xp:this.value><![CDATA[#{javascript:myCommunities.getTitle()}]]></xp:this.value>
		 </xp:text>
	</xp:div>
</xp:repeat>

and there we have it.

c2

So what is a Collection exactly? I guess I ought to find out……

IBMSBT in XPages: Getting set up with a Social Business Toolkit (Part #1)

In this article I will begin to introduce IBM Social Business Toolkit (SBT), provide links on how to¬†get it set up, talk briefly about how it works and then provide my first demo on how to get “My Files”.

The whole of this series will be based on “Smart cloud (now Connections Cloud)” as opposed to Connections on premises. This should not however really affect too much other than how you make the initial connection. After that the API is pretty much the same (for my purposes anyway).

Thank you Kathy Brown

Setting up SBT is not the easiest thing to do – nothing IBM ever is. But I owe a huge thank you to Kathy¬†who did the bulk of the hard work on this. Setting this up locally for me was pretty simple once she knew how. Part of the reason for me writing it down as I said before is self documentation ‘cos I know I will forget ūüôā

IBM SBT

Here are some links on how to set it up and configure it Рyou will have to install it on your server as well as in your Domino Designer.

Setting up on Domino Designer 

Download the latest code from OpenNTF (I used this one). Unzip the file locally and within there you will find the following folder

  • sbtsdk/redist/domino/

Within there you will find the com.ibm.sbt.domino.updatesite-1.0.3.20140723-1200.zip!. That is the file you need to reference when you install the feature into Domino Designer. (If you want to run the playground locally you will also need to install from the playground updatesite)

Setting up the server

Within the zip file references above you will find the features and plugins folders.

j1

Copy them and paste them onto your server in the following directory. The features and folders for the server are listed there.

DominoIstallPath\data\domino\workspace\applications\eclipse

I am sure there is a better “updatesite” way of doing it, but this worked for me *shrugs*

The XPagesSBT.nsf

The database within the zip file gives you some examples of how to work with the API and provides links and examples for the JavaScript API, Java API, XPages snippets and other examples. I am not going to use those examples. There is some cool out of the box feature but

  • The JavaScript API is far from complete (which is why I am learning Java)
  • The Java examples are not complete (which is why I am doing this from scratch)
  • The XPages examples and snippets are very “XPagey” and¬†I would rather do it myself

The faces-config.xml

Now this is the one useful thing you should get from the XPagesSBT.nsf because it contains all the managed beans used by the SBT to connect to Connections Cloud (and Facebook and Twitter and others). In there you will find examples for connecting to smartcloud and connections. You will need these in your quest to create an SBT application.

You will find this file through the Package Explorer, in the WEB-INF folder

j2

Setting up Connections OAuth app

Setting up a Smart (Connections) Cloud “App” for OAuth

Within Connections Cloud, not much less ew, but at least all browser based. This is how to register your app and get the OAuth tokens.

j1

 

 

j2

j3

 

j4

j6

j7

 

In the next article we will actually create our first example to Authorize and pull personal data from Connections Cloud.

 

 

 

 

Scrolling to the errors – Making XPages Error Handling more user friendly

In this article I will demonstrate how to easily improve the server side form validation process from a user’s perspective.

Introduction

I have to admit that I am not a fan of server side validation. While it suits the developer, it is often not a good user experience. If you complete a large form, hit submit and you have errors returned, it is had to ascertain where the error has occurred. This causes the user to have to scroll up and down the page looking for the error. In an ideal world the form needs to be validated fornt end and back end to provide the optimal experience, while ensure data integrity within the application.

When building the PSC Contest site http://contest.psclistens.com I wanted to make the server side validation as painless as possible for users.

Basic Server side XPages validation

To validate a field on an XPage we use validators and a custom message. In the following example, when the user submits a blank field, an error message will be returned and the JSF validation will prevent the form from saving.

<xp:inputText styleClass="form-control"  disableTheme="true"  value="#{competition.First}"
	id="first1">
	<xp:this.attrs>
		<xp:attr name="placeholder"
			value="Contact First Name">
		</xp:attr>
	</xp:this.attrs>
	<xp:this.validators>
		<xp:validateRequired loaded="true" message="This value is required">
		</xp:validateRequired>
	</xp:this.validators>
</xp:inputText>
<xp:message id="message6" for="first1"
	styleClass="error">
</xp:message>

Here is an example of the failing field. I¬†have assigned a class = “error” to the message and that styles it red and bold.
c1

Scrolling to the error message

Within the onComplete event of¬†the form’s submit button we can add some code to determine if there are any errors. If there are errors we can use some jQuery to “scrollTo()” the message on the screen and it is revealed to the user.

  • The code var temp = $(‘.error:visible’) selects all the error message which are visible to the user.
  • If the length of the selector is greater than 0 there must be an error on the page
  • So¬†determine where it is on the page¬†temp.eq(0).offset().top-250 and then
  • Animate a scroll to the element.
  • http://api.jquery.com/scrolltop/ tells us that we are able to ascertain the scroll bar height of the element and ¬†“Setting the scrollTop positions the vertical scroll of each matched element.”
<xp:button value="Submit" styleClass="btn btn-primary theSubmit" id="button1">
	<xp:eventHandler event="onclick"
		submit="true" refreshMode="partial" immediate="false"
		save="true" refreshId="container">
		<xp:this.onComplete>
			<![CDATA[
				//Check to see if there are any errors
				var temp = $('.error:visible')
				if (temp.length >0){
					$('html, body').animate({scrollTop: temp.eq(0).offset().top-250}, 1000, function(){
					});
				} else {
					alert('Thank you for your submission. PSC will be in touch.')
					location.href="http://www.psclistens.com"
				}
			]]>
		</xp:this.onComplete>
		<xp:this.script><![CDATA[
			//check to see if project sponsor is checked
			if ($('.projectSponsor').is(':checked')){
				console.log('sponsor check')
				app.checkSponsor()
			}
		]]></xp:this.script>
	</xp:eventHandler>
</xp:button>

If there are no errors the user is thanked and redirected to the PSC homepage.

Don’t do a complete submit….

The only way we are able to run an “onComplete”¬†on the button event handler is if we do not submit the entire form. If we do this then all the code will be lost and the page will revert to the top of the page.

Wrap the body of the form in a panel or div which can be refreshed.  Set the button click to partial refresh that section. This way the scroll position on the page will not be lost when the button is clicked.

 

c2

The contest site

Check out the contest site http://contest.psclistens.com before 13 Feb 2015 when PSC will announce the winner

 

Angular in XPages: Formatting Domino Data Services Date values with app.filter

In this article I will show how we can use the core angular date filter capabilities to format Date format, Domino data into an Angular.js based application

Introduction

In previous articles I have shown how to create a simple Angular.js application using a notes Domino Data Services feed from a notes database. If we want to add “date”¬†information then we need a way to nicely format it. Using¬†the Angular.js documentation page as reference I will show you how we can do this with Domino data.

Adding dates to our view

When we add a date field to a Domino Data Services feed we get something which is to the human eye¬†pretty “ugly”

a1

And when we add lastModified into our template, it is well, less than appealing….

a2

 

Adding a formatting function to the template

We can modify the template to use a formatting function by changing up the template slightly and then adding a formatting filter to the application.

In the app.js we add the following

personApp.filter("formatDate", function () {
    return function (x) {
        return new Date(x);
    };
});

And then we reformat the template as such:

    <tr ng-repeat="person in people"  on-last-repeat>
        <td>{{person.firstname}}</td>
        <td>{{person.lastname}}</td>
        <td class="zipCode">{{person.zip}}</td>
        <td class="user">{{person.username}}</td>
        <td class="user">{{person.lastModified | formatDate | date:"dd MMM yyyy" }}</td>
        <td><a class="btn btn-info" href="#/person/{{person['@unid']}}">Edit</a></td>
        <td><a class="btn btn-warning" href="#/person/{{person['@unid']}}/delete">Delete</a></td>
    </tr>

The critical part is {{person.lastModified | formatDate | date:”dd MMM yyyy” }}.

The documentation unfortunately is not clear on this and I found this Stackoverflow example which worked perfectly. http://stackoverflow.com/a/25856275/1171653

The resulting page now looks formatted and much easier to read

a3

Conclusion

I spent which a lot of time failing to achieve this date formatting without doing it the angular way. One quick google (or three) and I had the answer. Do it the angular way and oo look that that nice and simple formatting.

Websockets in XPages: Improving on the automated partialRefresh interface

In this article I will¬†further discuss how tom improve the user experience of an automated partial Refresh on an user’s XPage. Although these posts were originally about using Bluemix to host the node.js server I kinda feel that the focus has drifted onto websockets more than Bluemix. So in an attempt to make it easier to find I am going to¬†use the Websockets in XPages title moniker for a few posts and then go back to Bluemix ūüôā

Introduction

In the last article¬†we looked at how to push a automated partialRefresh to a¬†XPage application using websockets.¬†In that article it was noted that the user experience was not ideal¬†because the whole panel refreshed without the user knowing about it. For some apps that is appropriate and for others it may not be. At this point in his career¬†Dave Leedy is impressed he gave someone else and idea and I quote: “wow! that‚Äôs fricken awesome!!!”

So, that’s not a great user experience – what if they were doing something at the time?

Yes I was thinking that too! So I believe we can improve the user experience a little and take what Dave suggested and tweak it a little.¬†Now where¬†have a seen something which let’s the user know there is new data changes but doesn’t refresh the page without their action……….

b4

oh yeah that.

Instead of refreshing the control automatically, we will make the message create a “refresh” icon on the page which the user can then update at their¬†leisure.

b5

The modified code is¬†all in¬†what happens when the page receives the refresh socket message. I added a jQuery rotate function just for some added “je ne sais quoi“.¬†In the function we can see that when the refresh event is detected¬†by the socket code the refreshControl function is¬†called. This in turn makes the hidden refreshIcon visible, adds an onClick event and then rotates it. The onClick event performed the partialRefreshGet as we saw in the previous example turning the page briefly grey. We then hide the icon and remove the click event (to avoid piling on multiple events as the page gets continually refreshed)

 

 // Function to add a message to the page
  var refreshControl = function(data) {

	  $('.refreshIcon')
	  	.css({display: 'block'})
	  	.on('click', function(){
	  	   var temp = $('[id*='+data.refreshId+']').css({background: '#CCCCCC', color: 'white'}).attr('id')
		   XSP.partialRefreshGet(temp, {})
		   $(this).css({display: 'none'}).off('click')
	  	})
	  	.rotate({
	      angle:0,
	      animateTo:360,
	      easing: function (x,t,b,c,d){        // t: current time, b: begInnIng value, c: change In value, d: duration
	          return c*(t/d)+b;
	      }
	   })
  };

  // When a refresh message is received from the server
  // action it
  socket.on('refresh', function(data) { refreshControl(data); });

The following video quickly demonstrates the new capability.

Conclusion

In this brief article we concentrated on how to improve a user experience by notifying them that changes were pending and then allowing them to determine when the changes were made.

I still don’t think this is as optimal as I would like but you get the idea. As I said a long time ago – the more DOM you are reloading the worse the user experience. With a viewPanel we are kinda limited on what we can and cannot refresh. A better option may be to architect the application¬†just the new data and update as appropriate……….