Contents


Taking control of the IBM Connections user experience

Introducing IBM Connections Customizer

Comments

Editor's note: The content of this article appeared originally in App Dev Resources for IBM Connections Customizer on GitHub.

If you’ve ever wanted to change the way IBM Connections looks or behaves, the new IBM Connections Customizer, coming soon, gives you the control you’ve been looking for. In this article, you’ll learn how Customizer lets you change the Connections user interface, and how you can get started using Customizer right away.

Customizer is a middleware service that lets you modify the IBM Connections user experience. In essence, it’s a proxy between IBM Connections and the end-user. It can intercept and modify requests and responses, so it can customize anything that flows through it, such as the behavior of APIs and the look-and-feel of the user interface.

The IBM Connections Customizer model is simple. The service performs customizations by injecting JavaScript, CSS, or other web resources into the HTML pages returned by IBM Connections in response to end-user requests generated in standard components like Communities, Profiles, Files, Homepage, and so on, as the user navigates the apps. The customization details (typically, what code should be inserted and on what requests) are defined by applications stored in the IBM Connections Application Registry (“App Reg”).

App Reg is a centralized design repository used to store and retrieve applications that customize and extend a variety of different IBM Connections services, including Customizer. In the cloud, App Reg is available to organization administrators via the Admin > Manage Organization > Organization Extensions menu path. There you can create and manage Customizer applications, which are simply JSON files containing design information defining the components that need to be targeted and the actions that need to be performed. Listing 1 shows a simple Customizer application.

Listing 1. Hello World Connections Customizer application
{ 
  "services": [ 
    "Customizer" 
  ], 
  "name": "Simple Customizer Sample", 
  "title": "My First Customizer App", 
  "description": "Perform a modification to the Connections Homepage", 
  "extensions": [ 
    { 
      "name": "Hello World Extension", 
      "type": "com.ibm.customizer.ui", 
      "path": "homepage", 
      "payload": { 
        "include-files": [ 
          "helloWorld/helloWorld.user.js" 
        ] 
      } 
    } 
  ] 
}

This application simply prepends "Hello World" to the title string in the Connections home page.

The JSON should be easy to understand.

  • The app is named “Simple Customizer Sample” and it extends the Customizer service.
  • It contains one extension, named “Hello World Extension”. (Note that apps can have many extensions.)
  • The extension type (“com.ibm.customizer.ui”) shows that it is a customization of the UI.
  • The extension path (“homepage”) shows that the customization applies to the Connections homepage.
  • A file named helloWorld.user.js is to be injected into the homepage.

Tables 1 and 2 summarize the properties you can use in the JSON.

Table 1. Generic Customizer application properties
PropertyDescription
NameString used to identify the extension
TitleShort string description (translatable for international audiences)
DescriptionLong string description (translatable for international audiences)
ServicesThe service(s) with which the application is associated
TypeString used to identify the extension point being implemented – required. Valid values:
com.ibm.customizer.ui
com.ibm.customizer.api
PathString used to identify the component to customize:
activities
blogs
communities
files
forums
global*
homepage
mycontacts
news
profiles
search
wikis
*Unlike the other path values, global does not represent a real URL path element. It is a keyword meaning “match all URLs.”
Table 2. Payload Customizer application properties
NameDescription
match: urlA regular expression used to provide more fine-grained target resource matching than the broad match specified in the path property
match: user-nameString used to identify one or more users as the target for the customization. Note that user names may not be unique in a given organization.
match: user-idString used to identify one or more users as the target for the customization. This property is unique in a given organization.
match: user-email String used to identify one or more users based on email address value
include-files List of files to be inserted into the response for a matched page request

A closer look at Customizer properties

As shown in Table 1 and Table 2, Customizer properties fall into two categories:

  • Generic App Reg Properties
    Properties defined for all App Reg applications across all services
  • Customizer service properties
    Properties specific to the Customizer service (everything in Table 2)

App Reg requires that applications specify the generic name, title, description, service, and type property values. The Application Registry specification does not require the path property to be specified when an application is created, but the Customizer service puts it to good use for every request it processes, as we’ll soon see. Therefore, in reality a path value is required for Customizer applications to work properly.

Of the generic properties in Table 1, only type and path need further discussion.

A type value is always the name of an extension point defined by a service. At present, Customizer defines only two extension points:

  • com.ibm.customizer.ui
    A declaration that the Customizer extension modifies the IBM Connections UI. The extension will be handled in accordance with a prescribed UI extension pattern. For example, any include files specified in the payload are injected into the response document.
  • com.ibm.customizer.api
    This extension point is reserved for future use. As a middleware proxy, Customizer can modify API behaviors, but that feature is not available in the current Customizer release.

The path property value typically represents a path element in the IBM Connections request URL, which in most use cases corresponds to a standard IBM Connections component. Consider the URLs displayed in Listing 2.

Listing 2. Examples of IBM Connections URLs
/* homepage */ 
//w3-connections.ibm.com/homepage/web/updates/#myStream/imFollowing/all 
//w3-connections.ibm.com/homepage/web/updates/#myStream/statusUpdates/all 
//w3-connections.ibm.com/homepage/web/updates/#myStream/discover/all 
//w3-connections.ibm.com/homepage/web/updates/#atMentions/atMentions 
/* communities */ 
//w3-connections.ibm.com/communities/service/html/ownedcommunities 
//w3-connections.ibm.com/communities/service/html/followedcommunities 
//w3-connections.ibm.com/communities/service/html/communityinvites 
/* files */ 
//w3-connections.ibm.com/files/app#/pinnedfiles 
//w3-connections.ibm.com/files/app#/person/7f37da40-8f0a-1028-938d-db07163b51b2 
/* blogs */ 
//w3-connections.ibm.com/blogs/roller-ui/allblogs?email=joe_schmoe 
//w3-connections.ibm.com/blogs/roller-ui/homepage?lang=en_us 
/* wikis */ 
//w3-connections.ibm.com/wikis/home?lang=en-us#!/mywikis?role=editor

These sample URLs follow a clear pattern, in which the next element after the IBM Connections cloud domain name identifies the Connections component or application associated with the request. The possible values of this element are the path values in Table 1 (homepage, communities, files, and so on).

As http requests flow through Customizer, it can query the Application Registry for any extensions relating to a given request URL and reduce the scope of the result set by specifying the particular in-context path value. A REST request from Customizer to App Reg for Files customizations would look like this:

appregistry/api/v2/services/Customizer/extensions?type=com.ibm.customizer.ui&path=files

This translates as, “Get all UI extensions registered for the Customizer service that apply to Files.” This explains why Customizer extensions must contain both a type and a path value. One detail to note about the path value is the special global keyword. This supports the use case where an extension needs to apply to all requests. For example, suppose you need to display corporate footer text at the bottom of every page in IBM Connections. Clearly, it would be inefficient to create an extension for every possible path value. The global path value solves the problem.

Processing payload properties

In response to the request shown above, App Reg returns the extensions that match the criteria as a single collection of one or more JSON files just like the one in Listing 1. Customizer then parses and applies the design metadata in the returned extensions, and that is where the payload data comes into play.

App Reg itself does not use payload properties. It simply passes them to the nominated service (Customizer, in this context) for processing.

Fine grained URL matching

The generic path property provides a coarse means of querying the Application Registry for extensions pertaining to a given IBM Connections component. The optional match properties inside the Customizer payload let you fine-tune extension filtering, to determine whether an extension is applied to a given URL request.

The match url property takes a regular expression and evaluates it against the current URL. If it matches, the extension is applied; otherwise, the extension is not applied. This is a powerful feature, as the following code snippets demonstrate.

Listing 3 shows a Communities extension that has a fine-grained URL match applied on lines 14 – 16. In this case, the extension is applied only if the Communities followedcommunities URL is being processed. The extension is ignored for other Communities URLs like those shown in Listing 3; for example, ownedcommunities, communityinvites, and so on.

Listing 3. Customizer application with URL matching
{ 
 "services": [ 
   "Customizer" 
 ], 
 "name": "Communities Customization", 
 "title": "UI Customization for Communities I Follow", 
 "description": "Sample to modify Connections Communities", 
 "extensions": [ 
   { 
     "name": "Followed Communities Customizer", 
     "type": "com.ibm.customizer.ui", 
     "path": "communities", 
     "payload": { 
       "match": { 
         "url": "followedcommunities" 
       }, 
       "include-files": [ 
         "flipCard/commListCardsFlipStyle.user.js " 
       ] 
     } 
   } 
 ] 
}

Similarly, the following fragment shows how a single global extension can be applied to Homepage and Communities but nothing else:

Listing 4. Global Customizer application with URL matching
 … 
   "path": "global", 
   "payload": { 
     "match": { 
       "url": "homepage|communities" 
     }, 
 …

Note: The design of some IBM Connections components, like Homepage, is based on the Single Page App paradigm. For example, look at the Homepage URLs in Listing 2. All contain hashtags, which means that new http requests are not fired as the user navigates around the page. Therefore, Customizer is not notified when, for example, a user moves from imfollowing to atmentions. In contrast, Customizer is notified when a user in Communities moves from ownedcommunities to followedcommunities. You can target individual Communities URLs with the match url property, but you cannot use the same technique to match the Homepage hashtag URLs. Instead, your homepage extension would need to inject a script that listens for hash change events and responds accordingly. For an example, look at the triggerHashChangeEvent() function in the homepage sample newsRiverSectionedHashChange.user.js. (All the latest samples are in the samples folder of ibmcnxdev/customizer on GitHub.)

It’s easy to imagine many other uses for fine-grained match criteria. For instance, if you want to apply a customization to any Files URL that contains a GUID, you can set the path value to “files” and the match url value to “id=[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}”. For an example of such a URL, take another look at Listing 2.

Note: The braces in the regular expression must be escaped (that is, preceded by a backslash character) when included in JSON stored in App Reg.

Fine-grained matching based on the active user

The match property also accepts various user-related conditions based on the current user’s name or id. In both cases, you can specify single- or multi-value parameters—or, in JSON parlance, a single string value or an array of string values. Listing 5 shows how a Communities extension can target specific users based on their user names.

Listing 5. Customizer application targeting specific users by name
 … 
 "path": "communities", 
 "payload": { 
   "match": { 
      "user-name":[ 
         "Jane Doe", 
         "Joe Schmoe" 
      ] 
   }, 
 …

Since user names are not always unique in an organization, you might inadvertently target unintended users with this technique, so that all users with the same name see the extension. To avoid this scenario, you can use the user-id match property instead, as shown in Listing 6.

Listing 6. Customizer application targeting specific users by ID
… 
 "path": "communities", 
 "payload": { 
   "match": { 
     "user-id":[ 
       "20071635", 
       "20071656" 
     ] 
   }, 
 …

The story so far

So far, we’ve learned that:

  • Customizer is a proxy through which all Connections requests and responses flow.
  • Based on the URL requests it processes, Customizer queries App Reg to ascertain if customizations have been registered for Connections components.
  • When App Reg returns application definitions to Customizer, Customizer uses the metadata in the JSON payload to decide if a customization should be applied.

Figure 1 shows this request processing mechanism.

Figure 1. IBM Customizer request life cycle
IBM Customizer request life cycle
IBM Customizer request life cycle

Now, how does Customizer manage the file resources listed in the include-files property?

Managing application file resources

The include-files payload property lists one or more files to be inserted into the response, thus becoming part of the DOM structure loaded in the user’s browser. Listing 1 shows a simple single-item value for this parameter: "helloWorld/helloWorld.user.js", where helloWorld is a folder and helloWorld.user.js is a JavaScript file in it.

On IBM Connections Cloud, files declared in the include-files property are stored on an internal, persistent volume accessible only by an IBM Connections Cloud administrator or dev ops staff. They are retrieved for injection as needed by a Customizer microservice at run time.

To make your include files available on IBM Connections Cloud, you must use a Web-based source code repository. Right now, GitHub is the only supported repository. Others may be added in the future. If you don’t have a GitHub account, creating one is straightforward, and free for public and open-source projects.

Once you have a GitHub account, create a source repository to store and manage your Customizer include files. When you are ready to deploy those resources to IBM Connections Cloud, complete the following steps.

  1. Share your repository with IBM on GitHub.
  2. Issue a pull request to IBM when your extension is ready.
  3. IBM merges pull requests once its acceptance criteria are met. Repository files are pushed to IBM Connections Cloud via a webhook upon merge.
  4. Repeat, starting with step 2, as needed for extension updates.

"IBM Connections Developers" is the IBM GitHub organization you need to collaborate with, for activities like repository invitations, pull requests, issues, and so on. Refer to Figure 2 for more details.

Step 3 involves a lightweight summary review by IBM, which looks at various aspects of the proposed customization, primarily from a performance and security standpoint. However, ultimate responsibility for the behaviour of the Customizer application remains that of the customer who creates or adopts the extension. The review process by IBM provides no guarantee whatsoever of protection against adverse security or performance impacts.

Note: If you have a private GitHub repository, you can still share it with IBM Connections Developers, and it will only be visible to administrators of that organization.

Figure 2. IBM Connections Developers organization on GitHub
IBM Connections Developers Organization on GitHub
IBM Connections Developers Organization on GitHub

Tip: More information on how to integrate your Customizer include files with IBM Connections Cloud is available in the IBM Connections Customizer Episode 2 video on opencode4connections.org.

Inside a Connections Customizer include file

What exactly does the helloWorld.user.js include file do? Listing 7 shows the code. Certain variable names and comments have been trimmed for readability, but nothing that affects the execution of the script.

Listing 7. Hello World include file
if(typeof(dojo) != "undefined") { 
  require(["dojo/domReady!"], function(){ 
    try { 
      // utility function to wait for a specific element to load... 
      var waitFor = function(callback, eXpath, eXpathRt, maxIV, waitTime){ 
        if(!eXpathRt) var eXpathRt = dojo.body(); 
        if(!maxIV) var maxIV = 10000; // intervals before expiring 
        if(!waitTime) var waitTime = 1; // 1000=1 second 
        if(!eXpath) return; 
        var waitInter = 0; // current interval 
        var intId = setInterval( function(){ 
          if(++waitInter < maxIV && !dojo.query(eXpath,eXpathRt).length) 
           return; 
 
          clearInterval(intId); 
          if( waitInter >= maxIV) { 
            console.log("**** WAITFOR ["+eXpath+"] WATCH EXPIRED!!! interval "+waitInter+" (max:"+ maxIV +")"); 
          } else { 
            console.log("**** WAITFOR ["+eXpath+"] WATCH TRIPPED AT interval "+waitInter+" (max:"+maxInter+")"); 
            callback(); 
          } 
        }, waitTime); // end setInterval() 
      }; // end waitFor() 
 
      // here we use waitFor to wait for the 
      // .lotusStreamTopLoading div.loaderMain.lotusHidden element 
      // before we proceed to customize the page... 
      waitFor( function(){ 
        // wait until the "loading..." node has been hidden 
        // indicating that we have loaded content. 
 
        dojo.query("span.shareSome-title")[0].textContent="Hello World! "; 
 
      }, ".lotusStreamTopLoading div.loaderMain.lotusHidden"); 
 
    } catch(e) { 
      alert("Exception occurred in helloWorld: " + e); 
    } 
  }); 
 }

For a simple Hello World example, this may appear more complicated than you would expect, but closer inspection simplifies matters considerably.

  • Most of the code is a re-usable template.
  • Only one line of code (line 32) is needed for the actual Hello World UI update.
  • The IBM Connections user interface uses the Dojo framework, so the code is injected into a Dojo structured page.

The JavaScript code first validates that Dojo itself is loaded, and then uses a standard Dojo utility (domReady) to wait for the DOM to fully load before calling a bound function to perform the customization. Lines 2 – 23 define a function (waitFor()) that waits a maximum of 10 seconds for the page to fully load. If the page loads within 10 seconds, the function executes a callback function. Otherwise, an error is logged to the JavaScript console.

Figure 3. Hello World extension for IBM Connections Homepage
Hello World extension for IBM Connections Homepage
Hello World extension for IBM Connections Homepage

The waitFor() function call passes in the callback function to manipulate the DOM and modify the UI. The interesting part of the callback function (line 32) locates a DOM element and assigns “Hello World” as the text content. When Customizer loads and runs this extension, the IBM Connections Homepage is modified as shown in Figure 3.

If we view the source of the IBM Connections Homepage in the browser, we can see the code injection at the bottom of the page, as shown in Listing 8.

Listing 8. Customizer script injection
… 
<script type='text/javascript'
src='/files/muse-static/helloWorld/helloWorld.user.js'>
</script> 
…

Tip: IBM Connections web pages contain many predefined JavaScript variables that Customizer extensions can use. For instance, lconn is an object with many properties that any extension script can exploit. Thus on line 3, replacing "Hello World: " with "Hello " + lconn.homepage.userName + " " dynamically includes the current user in the Homepage customization. Exploring the lconn object and others like it will show you many valuable features that your extensions can leverage.

Other samples

Besides Hello World, a number of other ready-made Customizer examples are available for experimentation. You can always find the latest samples in the samples folder of ibmcnxdev/customizer on GitHub.

Each sample has its own subfolder, which contains the App Reg design definition (JSON file) and the resources to be injected to perform the customization (JavaScript, CSS). Take a look at the following examples:

flipcards

This extension provides an alternative rendering for the Communities pages, so that a user’s communities can be displayed as flip cards rather than a table of rows. Figure 4 shows a list of three communities, with the traditional row-based rendering on the left-hand side juxtaposed with the flip card layout on the right. Each flip card displays the Communities logo until the user hovers over it, whereupon the card is flipped to display the details of the community.

Figure 4. Communities page before and after flipcard customization
Communities Page before and after Flipcard Customization
Communities Page before and after Flipcard Customization

flipCard.json follows the standard App Reg pattern used in the Hello World example. commListCardsFlipStyle.user.js uses the sample Dojo wrapper to envelope the customization, but the code itself is significantly more advanced and serves to give a more real-world indication of what’s possible with Customizer extensions. When the customization is applied, look for the Toggle Extension control on the Communities page. Clicking the button lets the user switch between the standard row layout and the flip card format.

newsRiver

This extension targets the IBM Connections Homepage and reformats the layout of the activity stream updates by accentuating the space surrounding each entry. Figure 5 shows the Homepage with the newsRiver customization. Note how the entries display as sections against a pink backdrop. Also notice that the Hello World extension is also applied to the Home page. This shows how multiple App Reg extensions can target the same IBM Connections path. If you view the source of the page, you will see two JavaScript file injections.

Figure 5. Multiple extensions for IBM Connections homepage
Multiple Extensions for IBM Connections Homepage
Multiple Extensions for IBM Connections Homepage

profiles

This extension delivers a more sophisticated rendering of the page that is displayed when the user selects the “My Profile” dropdown menu option in IBM Connections. The new appearance is achieved with stylesheet updates. In the profiles subfolder, profilesCustomization.js simply inserts a link to profilesCustomization.css, which does all the work. The new look is shown in Figure 6. Note the inclusion of a new page header graphic, the relocation of action buttons, and so forth.

Figure 6. Profile page extension
Profile Page Extension
Profile Page Extension

Getting up and running

At this time, organizations in IBM Connections Cloud are enabled for Customizer by request only. In the future, it is envisaged that Customizer will be automatically enabled for all organizations. Meanwhile, the enablement request process is quick and easy. Simply send an email requesting Customizer enablement to ibmcndev@us.ibm.com and include your full name, organization name, and id. The request is typically completed within 24 hours.

The include files for all samples discussed in this article are automatically provisioned to any Customizer-enabled organization. This means you can use the samples immediately by importing the JSON files into your organization’s Application Registry. For example, to validate that your organization is Customizer-enabled, import the helloWorld.json file into App Reg.

  1. Make a local copy of helloWorld.json.
  2. As an organization administrator user, go to Admin > Manage Organization > Organization Extensions.
  3. Click Add > Choose File on the “upload an extension from a JSON file” radio button option.
  4. Select your local copy of helloWorld.json.
  5. Click Enable Editing.
  6. Insert a match criterion like the one in Listing 6 so that the extension is only applied to you. Match to your user-name, e-mail address, or user id.
  7. Click Add to save the application in App Reg.
  8. Refresh the IBM Connections Homepage and verify that the Hello World extension appears.

If the customization does not appear, report the issue in the ibmcnxdev/customizer GitHub repository, or email ibmcndev@us.ibm.com.

Tip: The steps above are covered in the 'IBM Connections Customizer Episode 01" enablement video on OpenCode4 Connections.

You can experiment with the other samples in a similar way. You may notice that some samples use a JavaScript filename notation that follows the GreaseMonkey naming convention: somename.user.js. These customizations were originally developed as GreaseMonkey scripts using browser-based extensions. They were then deployed on the server in IBM Connections as Customizer extensions. This is standard practice for developing Customizer apps. First create a new browser extension using a user script technology like GreaseMonkey for Firefox or TamperMonkey for Chrome. Once you are happy with the local customization, submit the resources to IBM for review. The JavaScript and CSS files you create using GreaseMonkey or TamperMonkey become your Customizer include files. You can then invoke the customization by creating a Customizer extension in the Application Registry.

Some points to note regarding Customizer applications

Support for Customizer applications follows the same policy as any other customization to the IBM Connections user interface. IBM Support can address questions about the customization process, but cannot address questions about the particulars of your customization.

Listing 2 provides the list of currently supported paths for Customizer. This list currently encompasses all core IBM Connections components with the exception of the Administration URLs (BSS), Docs, Meetings, and Verse. The list may be expanded to include these and other components in the future.

Customizer extensions are currently restricted to the organization in which they have been added. Users from one organization may have access to communities in other organizations if they have been invited, but they will not see any customizations added to the “external” communities.

Useful links


Downloadable resources


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Collaboration
ArticleID=1050997
ArticleTitle=Taking control of the IBM Connections user experience
publish-date=10312017