smart UI in practice: SMART TOOLS(1) – the beginning

smart tools

Using OpenText Content Server as as developer, you have to face it sooner or later: Write an application in smartUI. This will give you a lot of experience for smartUI projects, especially on the Cost/Times/Materials base.

I did chose to build a product called SMART TOOLS with Renditions and Multilingual Metadata Support. Product means, it can be sold by other OT partners as well.

This is a multipart post. Today we talk about the basics of the application running in Content Server 20.2. Additional posts will explain the usage and some technical aspects

Features

SMART TOOLS includes these features:

  • Adds support for Multilingual Metadata to smartUI
    • Automatic Translations for the multilingual data using Microsoft Azure REST service (as nobody speaks all languages on this planet)
    • Add print lists (to get a list of the data entered for editing)
    • Add/edit mlm data directly
    • Integrated in the standard nodelist widget using the property manager
  • Adds support for Renditions
    • List all Versions and Renditions
    • Use “view as webpage” as a base viewer
    • Download renditions
    • Delete renditions
    • Replace renditions
    • Add Renditon as command
    • A cell icon marks all documents in the document list having renditions at the newest version. Clicking on the icon will open a window to show all renditions. Download or delete a rendition.
  • Adds configuration support for the javascript client software from the Admin pages. Critical things like MS Rest API key can be protected by sending this things at the page creation time to the client.

The SMART Tools are build for Content Server 20.2. A a considerable amount of new REST services also to be implemented in the Content Server.

The Integration

Integration is simply direct in the nodelist widget using the property manager.

Open the property manager

By clicking in the first icon in the list, the property manager opens.

Renditions and Multilingual Metadata

The panels adressed by this menu are the multilingual metadata panel (with the two fields Name and Description) and the rendition panel. Here you see the mlm panel with the autotranslate Icon (the globe at the right).

mlm main panel

This is the rendition panel which shows all renditions attached to all versions.

Renditions main panel

Language support

The SMART TOOLS support a couple of UI languages like

  • English
  • German
  • French
  • Spanish
  • Italian

This is one example on the multilingual metadata dialog using German, French and English.

The nls feature of smartUI is nice, isn’t it? I even tried it (experimental) for Arabic, and it worked!

Lets go more in detail in the next posts, as this here is intended to be a simple overview.

Next week I will describe the multilingual metadata support of smartUI

Conditional Configuration with require.js in OpenText smartUI

Optional loading of modules

When you write a widget or something else in smartUI, you encounter (from time to time) the problem to provide your widget with different configurations.

Like one widget provided as DashBoard for Music Events and lateron provide the same Widget as Dashboard for Race Events with different Logos Graphics etc. Require.js conditional loading of a module will help.

The idea is, if a conditional configuration module exists, it will be loaded and override the standard configuration. If its not present at the defined place, it wont load this and use the existing configuration.

Lets see an example:

in a view, we define a config.js containing all configuration stuff of this module

The main View
The main View with the config.js declaration

This will load configration values like

Top of a configuration module
End of the configuration module
Mid of the configuration Module with the value "backgroundcolor" which we want to override
We want to override the value “backgroundcolor”

So far so good. When we want to override for example the value “backgroundcolor”, we can do that by editing the file, but we would have to redo that for all diffenent configurations. Its much smarter to define an optional require.js module, that will be loaded if present.

Our alternative config.file is called targetconfig.js.

Here are the values to replace the original ones.

For simplicity it contains only the value “backgroundcolor”.

The logic is:

If targetconfig.js exists, it will be loaded with require.js and replace the specific contents of the original config.js file with the contents in targetconfig. If its not existing, its simply doing nothing and the original config will be used.

How is this done?

First, we have to declare the additional targetconfig.js in the define area as optional.

Optional declaration

Second, we must add a require.js module called optional doing the job

The require.js optional module

Now, we can use this in our wonderful widget providing as much configuratíons as we want – based on the existence of this config files.

Welcome to the Wonderful world of OpenText smartUI!!!

New: We are offering custom widget development. Interested? Send an e-mail to merz at ebit-company.de stating the purpose of the widget and requesting a qoute

Routers in OpenText SmartUI

greetall screenshot

Inside a Single Page Application, a router will take care of that what a URI used to do for you in a classic Client/Server application, it will intercept the URIs from beeing send to server and decide based on the URI whats to do with it. All within Javascript (we are not talking about html5 push state, thats another story)

Normally, the router will change the perspective (the display page) depending on the URI. For example, if an URI is http://<yourserver>/app/greetings, the Router will change the perspective to some new widgets and display the contents.

There are 4 routers build in the sdk (all in csui\pages\start\impl)

  • node.perspective router
    switches to a different node
  • landing.perspective.router
    used to address landing pages of the users
  • search.perspective.router
    switches to the search perspective requested
  • Perspective.router is the parent object of all routers in the sdk

A router changes the perspective, for example a node perspective

var nextNode = context.getModel(NextNodeModelFactory);

nextNode.set(‘id’, 2000);

Normaly these routers shoudl be enough for standard usages, but if you need your own router, the next example can bring some light into a routers anatomy.

Scenario:
there are two routes in an URI, “greetings” and “greetings/:id”.

“greetings” clears a greeting subject, which was initialized from the model factories) and sets the id and “greetings” in the application scope

“greetings/:id sets the id in the greetings subject

The greetings router

_updateURL constructs the URL and moves to this URL.

Next, we neet plugin with two tasks:

  • –Get/create the model and switch perspective depending on the subject
    • In _fetchHelloPerspective
  • –Set the greetingSubject in the constructor
Thed greetings router plugin
Process local perspectives with a plugin

We defined two routes, so we must provide two perspectives. We want to load them not from the server, so we need to define them locally als json arrays.

the greetings/:id perspective
The perspective for the greeting/:id simply displays the greeting widget
the greetings perspective
The perspective for the greeting displays the hello widget
the extension points
The extension points for the router

And this thing works (see these screenshots)

example of a greetings route
URL localhost/cs162/cs.exe/app/greetings called
example of a greetings/reiner route
URL localhost/cs162/cs.exe/app/reiner called

Imagine the possibilities. You can add a bunch of functionalities to the client all with an URI, which can be behind a link or a button.

Quite powerful, the smartUI sdk! You will love your routers.

The Connection Object in smartUI

Setup of the Connection Object

smartUI does have a couple of interesting objects, but the actual documentation about them is not very clear. So lets take a look on the objects.

First, we’ll examine the connection object a little bit more in detail. The page context will follow in another post.

The connection object provides information about the content server to connect with. Normally, this object comes from the content server but has to be constructed manually when you use the index.html testing facility.

Lets take a look at a typical index.html with the connection object setup

Setup of the connection object

Remember, the widget will get everything beeing perfectly setup from the content server, but using the test faciliy, you have to mock up this.

Parameters:

  • url – the url which is the content server url in your mockup data
  • supportPath – where is your content server support directory
  • credentials – in case you want to log in, use this clause
  • session- when you want to ignore the ticketing etc, use ticket:”dummy”

Lets see what this object is doing:

(here the page is running and this is a screenshot from the debugger)

A debugging session with the connection object

We see, there is a connector object beeing the parent for the connection object. The connection object contains all parameter setups from the index.html, mainly the url and the session infos.

There is also an Authenticator in this connector object, which contains another copy of this connection object but also with the information, how the automatic re-login for a valid session ticked should be done. And of course, the type of Authenticator (here InteractiveCredentialsAuthenticator)

(Remember: The security token timeout will cancel your session (within typically 300 sec) if you do not a relogin).

This is the mechanism to avoid permanent logins. Take a look at the available authenticators to see the possibilities.

You can always refer the Connection Object to get the url of the server. This url os merged with the parameters in the Model URL function to build the final REST call.

A useful object. Normally we get it automatically from the server, only while testing with Mock-Up Data we need to setup this object manually.

Config Settings send to a smartUI Module

There are several possibilities to set the configs from the base OScript Module. The most interesting is the method of setting the configs via Oscript. The complete list of the possibilities is_

  • When you visit a mode or get a children
    • Implement “fields” and/or “expand” in the appropriate CSNode.
    • Use the date from data.(fields.name)
  • When the Widget is created
    • Implement an REST service which will give you the data
    • Load the data on the first widget creation and cache it with a permanent model factory in the context
  • When the page is loaded
    • The CSUI::Extension::GetDynamicConfiguration method in OScript has normally this entry
function Assoc GetDynamicConfiguration( Object prgCtx, Record request )      
return Undefined
  end

Overwrite it with your desired configuration (here only the enableAppleSupport is displayed for clarity):

 function Assoc GetDynamicConfiguration(

        Object      prgCtx,

        Record      request )      
Assoc       basicAppData
Assoc       config 
(snip)

        Boolean     enableAppleSupport

    (snip)

        // changes in admin page should be reflected immediately by every thread

        settings = $WebAdmin.AdminUtils.GetSmartUISettings( prgCtx )
     (snip)
    if ( IsFeature( settings, "enableAppleSupport" ) && IsDefined( settings.enableAppleSupport ) )

        enableAppleSupport = settings.enableAppleSupport

    end

    

    config = Assoc{ 
    (snip)
     "csui/utils/commands/email.link": Assoc{ "enableAppleSupport": enableAppleSupport },
                  

    return config

end 

The returned assoc consists of a requirejs module name containing an assoc with the config values.

In your js module (here csui/utils/commands/email.link) add this line

var config = _.extend({
rewriteApplicationURL: false,
enableAppleSupport: false,
appleNodeLinkBase: 'x-otm-as-cs16://?launchUrl=nodes/'
}, module.config());

Then the config is avaliable in your js module and can be used like

var iOSEnabled = config.enableAppleSupport

Nice, isn’t it?

Find require.js module dependencies in smartUI

Have you ever noticed that the number of modules in a require Javascript enwironment can be huge? Difficult for an overview?

In this case, a graphical overview of modules and their dependencies can save you.

There are two solutions.

Non-Webstorm Solution

If you are using any text editor as a main Javascript Programming Tool, the npm dependo is a nice tool. Used against the MyAssignments Widget, it produces his output (click on the image to see a larger version)

dependo output

Installation:

$ npm install dependo

Usage:

$ dependo -f amd /path/src > example/report.html

will produce the graph in the file report.html

There is also a grunt task for dependo here

https://github.com/auchenberg/grunt-dependo

Webstorm Solution

If you are using the Webstorm IDE for your projects, there is a build in solution.

It produces against the MyAssignments Widget this chart (click on the image so see a high resolution version):

To get this diagram, click on the root of a widget and select

“Show Diagram Popup” shows the Drawing as a popup window, while “Show Diagram” shows the drawing in a new tab.

In Detail Mode you’ll see a lot more details, here are the external modules required by the main js module.

This gives you a lot of information and this can be also used to provide a technical system documentation.

Happy documenting.

Switch the smartUI SDK to Javascript ES6

When you start GRUNT, you will get errors on ES6 keywords, each LET will be flagged as error,

Have you ever wondered, why the SDK is not accepting JavaScript ES6? The wonderful new level of Javascript avoids for example the Variables Hoisting Effect by using LET instead of VAR. (Reduces the scope of the variables)

On the other hand, not all Browsers support ES6. So be aware that you may have to switch it back, if your browsers provide no support for ES6.

To change it:

  • open the node-modules folder in your project dir
  • scoll down until you find the module eslint-config-default . Edit the file .eslintrc in a tect editor (screenshots are from WebStorm IDE)
eslint config default in node_modules
eslint.rc

in this file, you’ll see that the file off.js is used for configuration. Open this file in a text editor.

The file off.js

Here you see, that es6 is set to false (Yellow Arrow). Change this to true and save the file (maybe under another name. In this case, correct the require command to reflect the new name).

So now the GRUNT-file is producing no problems when it encouters a LET.

But be aware: If your bropwsers lack some support for es6, you must switch back to ES5.

Practical Series II: Building an EVENT Management System in the Content Server using a graphical smartUI Dashboard and Connected Workspaces.

3-5 days, depending on the skills of the attendees.

Here, an EVENT Management system in the Content Server is built from the scratch. Events can be anything, from a Music Concert to Keysessions or anything else. To manage Events, all necessary Notes, Documents, Feedbacks can be stored in the Content Server.

Each event is mapped to a Business Workspace and has several folders to hold all documentation and feedback. Events can be related to other events. Each Event is containing Documents according to the template and has a Team of Coworkers. We also implement a Dashboard to see all Events in smartUI. If an Event is clicked in the Dashboard then the corresponding Connected WorkSpace Business Object is opened. Both parts, the Dashboard and the Business Workspace correspond via REST Service, which is also to be implemented during this workshop.

Uses the Content Server 16.2.10, the smartUI SDK and the D3 library, which is part of the smartUi SDK.

New: We are offering custom widget development. Interested? Send an e-mail to merz at ebit-company.de stating the purpose of the widget and requesting a qoute

Practical Series I: Strategies to “widgedize” an existing Content Server module and to add functionality in an existing widget.

1 day. Here, some practical parts of the SDK usage are discussed. First, we discuss, what’s to do, if somebody wants to use the Barcode Command (Enterprise Scan) as a widget in smartUI. We discuss what’s to investigate using CSIDE and implement the widget. Then the appropriate REST Services are implemented on the Content Server side. Then we add an email functionality to the TEAM widget by implementing this as a view and interconnecting this with the original widget using a command.

Practical Experience in the SDK or the Base Workshop is required.

New: We are offering custom widget development. Interested? Send an e-mail to merz at ebit-company.de stating the purpose of the widget and requesting a qoute

Agenda of the new 16.2.10 smart UI advanced Workshop

“Extended SDK Parts” 1.5 days

Content:

  • Additional Widgets
    • Webreports
      • NodesListReportView
      • TilereportView
      • FilteredCountChartView
      • Carousel Widget View
      • parameter.prompt.form
      • table.report
      • status.screen
      • open.webreport.js (action to show the Parameters form)
  • binf-Datepicker
    • Using the build in datepicker
  • binf-switch
    • Using the binf-switch to turn checkboxes and radio buttons into switches
  • Workflow
    • Workflow Components
    • Workflow in smartUI including Workflow Status (new in 16.2.4)
    • Starting Workflows
    • URL Routes
    • Workitem Model
    • Workitem Actions
    • Workitem Extension
    • Writing Workflow Extensions
    • REST API Support for Workflows
  • Connected Workspaces
    • Configurationvolume
    • Header
    • xECM: Office365 Groups
  • Extended ECM
    • xECM: Header Widget with Business Object Infos
    • xECM: Snapshot of current document Attachments
    • xECM: Dossier View Widget
    • Event Action Center
  • Widgets not part of the SDK
    • Mobile Scanning
    • Discussion Widget
    • Engineering Doc Management: Search
    • MyShares

“Extended SDK Features” 0.75 days

Content:

  • Build Language Packs for Internationalization
    • How to build an English language template
    • How to build the language pack
  • Commands
    • Implementation and Inheritance from “CommandModel”
    • Best Practices
    • Attributes, Methods
    • Using Commands
  • Custom URL Router.
    • Routing, adding custom Routers.
    • Using Routers as Navigation.
    • Perspective Routers
  • Authenticators and Regions
    • Authenticators
    • Non-Attaching Region
    • Non-Emptying Region
    • Script Executing Region
  • Behaviors. What are Behaviors?
    • DefaultActionBehavior
    • ExpandingBehavior
    • InfiniteScrollingBehavior
    • PerfectScrollingBehavior
    • Search Behavior
    • CollectionErrorBehavior
    • CollectionStateBehavior
    • ItemErrorBehavior
    • ItemStateBehavior
  • Mixins.
    • What are Mixins?
    • Discussion of the main mixins
      • LayoutViewEventsPropagationMixin
      • ViewEventsPropagationMixin
      • AutoFetchableMixin
      • NodeAutoFetchableMixin
      • ConnectableMixin
      • NodeConnectableMixin
      • FetchableMixin
      • ResourceMixin
      • NodeResourceMixin
      • UploadableMixin
      • CommandableMixin
      • ExpandableMixin
      • AdditionalResourcesV2Mixin
      • V2CommandableMixin
      • ExpandableV2Mixin
      • FieldsV2Mixin
      • RulesMatchingMixin
      • SyncableFromMultipleSourcesMixin
  • Browsable Support for Collections.
    • Using the “Browsable” support for Model-Collections.
  • Widget Options for the Perspective Manager
    • Wire up your widget options that they can be configured at the Perspective Manager Level

“Additional things to consider” 0.75 days

  • Tips and Tricks
    • Add a OTDS Ticket already in the browser to the connection object
    • Re-using a OTDS Ticket as LLCookie
    • Checking the paths in the test/index.html
    • Adding non CSUI supported jQuery functions in a view
    • Add additional jQuery Libraries
    • Adding Controls to a widget
    • CKEDITOR 4 new
      • Intro
      • JQuery Non-SDK example
      • Usage in the SDK
    • Handlebars advanced
      • Handlebars QuickStart
      • Expressions
      • Helpers
      • Helpers with html output
      • Helpers with Hash Object
      • The Helper fn property
      • The helper inverse property
      • Partials
      • Helpers in the SDK
      • 188 Handlebar Helpers
    • LESS advanced
      • LESS installation
      • Using LESS variables
      • Using Mixins in LESS
      • Parametric Mixins
      • Guarded Mixins
    • D3 new
      • What is D3
      • Basic Elements
      • Zooming and Panning
      • D3 in the smartUI SDK
    • Moment new
      • What is Moment?
      • Performing Time Calculations
    • Alpaca new
      • What is Alpaca?
      • Content Server Support for Alpaca
      • Alpaca Tutorial

“One or two more things” 0.5 days optional

  • Accessibility in Bootstrap. Screen reader support and what’s to change in the SDK to support screen readers for visual impaired users.
    • What is Accessibility
    • Kinds of Disabilities
    • Accessibility and the law
    • WAI-ARIA
    • ASSETS.CMS.GOV
    • PayPal Bootstrap Accessibility Plugin
    • Web Experience Toolkit WET
    • Other resources
    • Best Practices in smartUI development
      • Pre-Development Steps
      • Preparation Steps
      • Development Steps
      • Integration Steps
      • Documentation Steps
  • Development Infrastructure for security aware Organizations new
    • Recommendations what’s to do if the reloading of npm modules during the creation of a widget is not wanted

1 Day optional Discussion of actual problems

Discussion of actual problems

Here actual problems from the widget development are discussed. This part has to be discussed and defined in advance.

New: We are offering custom widget development. Interested? Send an e-mail to merz at ebit-company.de stating the purpose of the widget and requesting a qoute