The new smartUI Nuc. A closer look.

The new NUC package in smartUI

Disclaimer: The discussed topic is on Content Server 21.2 smartUI SDK and may change anytime without notice after today (I dont hope so, but….)

The new package nuc in the smartUI SDK is the

(quote) nucleus of the nucleus (endquote)

and something like “the Best of the best, Sir” (Men in Black I)

What is nuc?

Lets take a look at the lib/src folder in an initialized 21.2 project. To see the images larger, right click and open the image in a new tab.

Nuc, The Nucleus of the Nucleus

The nuc consists of these folders:

utils

This folder was located in the csui package in ancient time. Nowadays it has moved to nuc.

If you compare that to the csui/utils(21.1), you’ll discover a few differences

And also csui/utils(21.2)

If you use requirejs paths to elements, which are not in csui/utils(21.2), you should check these references and edit them to point to the proper element if needed.

models

This folder was located in the csui package in ancient time. Nowadays it has moved to nuc.

If you compare this with the csui/models(21.1), you’ll notice a few differences.

And also compared to the csui/models(21.2) there are differences:

A closer look reveals, that the csui/models(21.2) is not identical to csui/models(21.1) and therefore you are supposed to correct manually any requirejs paths in your js code, if you have to require those models moved from csui/models to nuc/models.

lib

This folder was located in the csui package in ancient time. Nowadays it has moved to nuc. The folder contains

If you compare that with lib at csui (21.1) and also with that lib folder existing in the csui (21.2), you’ll discover, that csui/lib(21.1) is the same as csui/lib(21.2), whereas nuc contains a subset of the entries of 21.1. At least on 21.2 the csui/lib references seem to work perfect, so that those in nuc/lib could be ignored.

grunt-tasks

This folder was located in the csui package in ancient time. Nowadays it has moved to nuc. It contains that:

If you compare that with the grunt-tasks at 21.1, you’ll discover a surprisingly large amount of additional documentation files. The old 21.1 csui/grunt-tasks had only the README.md, whereas there are a lot of additional md’s on 21.2 nuc/grunt-tasks available.

bundles

this is a new folder consisting of a couple of pre-defined bundles. These Defines([]) are quite handy to use. Nothing special here.

Amending the tabbed perspective

Tabs in the header: Playing hide&seek

In the tabbed perspective there is a nice game of hide and seek implemented. This gives you excellent entertainment, but you can amend this to simply display tabs as usually in any non-gaming environment. All examples here are displayed using the index.html from the /lib/src/csui/perspectives/tabbed.text/index.html. (Version 21.1)

The described way tabbed perspectives behave in smartUI is not a bug, its a feature.

The initial game

It goes like this:

The not so hidden hide&seek tab mode

If you have defined a header and several tabs, filled with standard data, you’ll see this initially. But when you click on any but the first header, the game is activated.

Hide&seek mode activated

A simple click on the tab name activates the hide &seek mode. The tabs try to hide and you are supposed to seek for them. This is really a nice and entertaining game.

The conservative Amendment

But what if you want to switch off this challenging mode?

Deactivating the hide&seek mode to allow the more conservative tab display

The build in hide&seek mode can be switched off by commenting this two lines in the tabbed.perspective.view.js.

A reload of the test page gives you by clicking to the second or thirth tab this:

The converwative Tab Display.

Although you switched of the hide&seek mode, you can now use the SDK to display the tabs in a more conservative way.

The smartUI SDK is very versatile and can be used for several purposes, even for conservative tab displays.

The only thing to decide for you is how to change that in the smartUI. Either spawn this into your own perspective or map your changed .js file over the standard requirejs path, this is up to you. You can even try to clear the cs-collapse.css and cs-toggling.css classes using the csui-stype-override-kit (I have not tested that for side-effects).

Happy tabbing.

New in Content Server 21.1: New Webreport Widgets and Extensions

Nodestable

There is already an amazing set of webreport related widgets in the smartui (like HTML Webreport, Nodes List WebReport, Visual Count and Widget Carousel) in smartUI along with a couple of controls, models and actions which make the usage of webreports in smartUI much easier (like parameter.prompt.form, table.report, status.screen, open.webreport, WRTextModel etc). More detailled informations can be found in my Training “Advanced Workshop Webreports”.
At the dawn of the new version, we got a couple of new and extended widgets to be used with webreports.

Some amazing new full-page widgets hit the road


New in Content Server 21.1: New Webreport Widgets and Extensions. They display a full-page of data in a folder or Business Workspace in the Smart View. Three new full-page Content Intelligence widgets are now available to use with Perspectives:

  • Nodes Table Report – Full page
  • Table WebReport – Full page
  • Visual Count – Full page

Users may want to display visual countable data as a full-page chart or present a list of nodes, for example documents to be processed, in a full-page format in the Smart View.
The new full-page widgets will also work with Business Workspace tabbed perspectives, to add various reports sourced using WebReports. Full-page widgets can also be used with other Perspective layouts.

New Webreport Destination

A new WebReport destination, Full Page Widget, sees action for the Nodes Table WebReport, Table WebReport, HTML WebReport and Visual Count destinations.
Once the Full Page Widget output destination is selected, the Nodes Table WebReport, Table WebReport, HTML WebReport or Visual Count can be selected for the Type.
To support the new transport destination added for full page widgets, the transport destination page now has references to the Table Report SubWebReport node and the Visual Count button node to be transported.

Nodes Table WebReport – full page

The Nodes List WebReport widget displays a list of items (nodes) generated from the WebReport’s data source in a full-page view, similar to the browse view.
Parameter prompts can be added for the user to input date ranges, attribute values, etc. using the commands, actions and models mentioned above (since 20.1). If in use, an edit pencil button will display to edit the parameters.
Custom columns, scrolling, name search and pagination are supported.
The node action menu and multi-select actions are available to work with the items in the result set.
All titles and labels support multilingual metadata.

Configuration is done this way. Configure thhis widget and add the title and the node id of the webreport to display in the perspective manager. An Icon Class displays the appropriate Icon on the widget.

Table Web Report – full page

The Table WebReport widget displays a list of items based on the WebReports data source in full page mode.
Parameter prompts can be added for the user to input date ranges, attribute values, etc. using the commands, actions and models mentioned above (since 20.1). An edit pencil button will display to edit the parameters.
Additional data columns, scrolling, column filtering for multiple columns and pagination are supported.
Additional actions can be added, for example a sub-WebReport to initiate a workflow, send an email or create a document node from the item.
Titles and labels support multilingual metadata.

Visual Count – full page

The Visual Count helps visualize countable data using a full-page chart in the Smart View. The chart view (can use bar, donut or pie) has controls for users to filter and drill into data easily.
Parameter prompts can be added for the user to input date ranges, attribute values, etc. using the commands, actions and models mentioned above (since 20.1). If in use, an edit pencil button will display to edit the parameters.
Action buttons can be added, such as export to CSV file, email report data and initiate workflow.
Titles and labels support multilingual metadata.
The Visual Count tile widget and full-page Visual Count widget has a new Horizontal Bar type option.
The original Bar type has been renamed to Vertical Bar to distinguish the two bar types.
The horizontal bar, vertical bar, donut and pie chart types can be changed in the Perspective Manager and Edit page.

New WebReport features

New Enable Row Filters Tag


This new tag [LL_WEBREPORT_ENABLEROWFILTERS /] is designed to automatically filter a WebReport data source when the report is used as a button with the Visual Count widget.
This has also been added to the tag guide as a general feature. This allows WebReports to have better out- of-the box support for dynamic complex filters.


Hidden columns allowed to be included in Table WebReport widget


A new tag option is now available for Table WebReport widgets, INCLUDEHIDDENCOLUMNS:, to specify a list of columns that you want to include in the data returned to the client for each data row. The column will not be included in the columns array in the response.

New in 21.1: Multilingual Metadata Support

Multilingual Metadata in 21.1

Finally, Multilingual Metadata Support is implemented in Content Server 21.1. Before that version there was only Support available here.

The Users Point of Vue

Multilingual Metadata can be added/edited at the Property Panel of a document. The first screenshot gives the entry of the name, the second gives the entry of the Description field.

Multilingual Metadata in 21.1
Multilingual Metadata in 21.1

Only Names and Descriptions are supported for Multilingual Metadata. For more fields or even Category Attributes in multiple languages, refer to an OpenText Partner like CASSIA.

The Programmers Point of Vue

The Name and Description fields show at least two multilingual text pickers. These are found in the SDK in /lib/csui/controls/multilingual.text.picker and in /lib/csui/dialogs/multilingual.text.picker. Unfortunately there is no Documentation and no index.html. Lets take a look on that control:

The Controls

The left screenshot is from dialogs, the right is from controls.

Multilingual Text PIcker

This is embedded in the header.view.js from the dialogs/node.picker and will only be activated, if Metadata Languages are enabled. The mixin allows the form to be displayed as a Bootstrap Popover.

Mixin Start

Changes in that area require the changed multilingu<al text picker and also the changed paths to be followed for that changes. Therefore require a spawn of the whole nodestable widget to reflect that changes. This is acually not recommended.

Happy MLM

The new Treebrowse Component – Nearly a Windows Explorer

Treeview Control

The Treebrowse Component is a new in Content Server 21.1. What’s a Treebrowse?

Let’s take a look at the index.html at csui/controls/treebrowse/test

Treeview Control

This is an additional Window with the tree based display of all folders in a Content Server. It can be configured that a click on the top left icon will switch it on and off. This Treebrowse Control will then change the display of a Nodestable according to the folder pressed.

Additional Features

Lazy loading and prefetch options for performance. There are a couple of options to configure the loading of the nodes for performance. A “Show More” button can be configured

Tree Navigation is in sync with Table View in Nodestable view. The Nodestable is displays the children of the selected folder.

Multiple root nodes can be configured.

Enable

This Treebrowse is always there, but it must be enabled.

define(['module',
'csui/lib/backbone', "csui-ext!csui/controls/treebrowse/navigation.tree"
], function (module, Backbone, moduleConfigs) {
'use strict';
var config = module.config(),
enableSystemLevel = !!config.enable;
moduleConfigs = moduleConfigs || [];
var configModel = Backbone.Model.extend({
defaults: {
sequence: 100,
enabled: function (status, options) {
return false;
},
data: function (status, options) {
return {};
}
}
}),
configCollection = Backbone.Collection.extend({
model: configModel,
comparator: 'sequence'
});

The var enableSystemLevel is interesting.

var NavigationTree = {
enabled: function (status, options) {
  if (!!enableSystemLevel) {
    return true;
  }
  var enabled                = false,
      moduleConfigCollection = new configCollection(moduleConfigs);
  moduleConfigCollection.some(function (mConfig) {
    enabled = mConfig.get('enabled')(status, options);
    if (enabled) {
      status.originatingView.treeData = mConfig.get('data')(status, options);
    }
    enabled = enabled ? true : enabled;
    return enabled;
  });
  return enabled;
}
};
return NavigationTree;
});

As you can see, the Enablement on a system level can be done in OScript. Refer to this post, if you want so figure out how.

If you want to configure this control only for certain folders, you should do:

  • Implement methods enable and data in a separate file and return them in an enclosed object.
  • Register this file which returns object containing enable and data methods as an extension to the “csui/controls/treebrowse/navigation.tree” in the respective module.
"csui/controls/treebrowse/navigation.tree": {
    "extensions": {
      "RMExtensions": ["RMExtensions/controls/treebrowse/RMExtensions.treebrowse.tree"]
    }
  }
  • Enable method should return a condition that specifies when the Tree Navigation should be enabled.
  • The data method should return data that must be passed to tree navigation while instantiation. This data should include configurable settings. If there is no data to be passed default settings are applied.

Example

define([], function () {
  'use strict';
  var RMTreeView= {
    enabled: function (status, options) {
       var supportMaximizeWidget = $("body").hasClass("csui-support-maximize-widget");               return (supportMaximizeWidget && $("body").hasClass("csui-maximized-widget-mode") === false);
    },
    data: function () {
      return {
        "lazyTree": true;
      };
    },
    sequence: 50
  };
  return RMTreeView;
});

A more complex enabled function (like in the index.html) is

enabled: function (status, options) {
var parent_id = status && status.container && status.container.get('parent_id');
return !!parent_id;
}

Parameters

  • Parameters thats need to be included as part of module config:
    • sequence – number default: 100 Decides the priority of a module when multiple modules enabled treeview.
    • enable – function controls whether the treeview command should be visible or not. Need to return a logic whether tree view command is visible.
    • data – function Returns an object of data that are passed to treeview. The parameters that are returned by the data method are passed as options to the constructor of node.tree.view.
    • Parameters that can be returned by the data method are::
      • lazyTree – Boolean default: false Decides whether to prefetch items at one level ahead to display without any delay on clicking showmore button / to fetch the items after clicking show more button.
      • showItemsBlockSize – Number default: 10 Number of items that are shown on expansion of any node or clicking on showmore button.
      • rootNodes – Array of nodemodels default: top most ancestor node of the currently active node An array of nodes which are used as root nodes by the tree. If more than one root node is provided then multiples root nodes are displayed.

Happy Tree Browsing!

The magic of Extension Points: the csui-ext module

require js

Have you ever thought of the magic of extension points in smartUI?

What is an extension point?

This are the dynamic configuration points of smartUI. Calling the config URL in smartUI, you will see all extension points with all configured extension modules in the current smarUI. Normally you’ll add your modules in the file <your-base-requirepath>-extensions.json in your projectstructure build by yo.

All of these modules indicated by these json files are loaded at initialization and form the dynamic smartUI system.

This is an example of an actual configuration in a Content Server System :

Extension Point

As you can see in the configuration, an extension point allows the extension of the extension point with several definable extension modules. Ok,this sounds like a typical lawyer sentence.

In plain english:

This technique allows you to extend the capabilities of a base module (the extension point) with the extension modules listed.

How to add your own extension point?

Use cs-ext as requirejs extensions. This is part of the SDK (/lib/src/csui/utils/load-extensions). There is the module and a very brief short documentation.

If you want more infos on custom requirejs modules, refer to the example of a conditional module,

This is a require.js module like the one which I introduced for conditional loading in Febr 2020. cs-ext is part of the smartUI core. If you want to modify the cs-ext, then use the easy way of loading an requirejs extension described in the conditional loading article.

Overview of cs-ext (in the sdk)

Lets take a look at cs-ext. But if you are more interested in the usage of cs-ext, skip the overview and go to the next chapter “Usage of cs-ext” below.

define(['module', 'csui/lib/underscore'], function (module, _) {
'use strict';

The cs-ext requires only module and underscore.

var config = _.defaults({}, module.config(), {
ignoreRequireErrors: false,
modulePrefixesToRetry: [
'csui', 'classifications', 'esoc', 'wiki', 'workflow', 'webreports'
]
});

This is the standard entry to add sme vars into the configuration. Interesting is the list of modulePrefixesToRetry, includes all modules to retry a reload, if the extension point loading fails.

function handleSuccess(onLoad, parameters) {
onLoad(Array.prototype.slice.call(parameters));
}

The success handler, handles the callback

function handleError(error, onLoad) {
if (config.ignoreRequireErrors) {
console.error(error);
console.warn('Loading extensions of "' + name +
'" failed:', error.requireModules);
onLoad([]);
} else {
onLoad.error(error);
}
}

The error Handler

function retryLoading(require, name, modules, onLoad, firstError) {
var droppedModules = [],
selectedModules = .filter(modules, function (module) { var slash = module.indexOf('/'); if (slash < 0 || .contains(config.modulePrefixesToRetry,
module.substring(0, slash))) {
return true;
} else {
droppedModules.push(module);
}
});
if (selectedModules.length && droppedModules.length) {
console.error(firstError);
console.warn('Loading extensions of "' + name +
'" failed:', firstError.requireModules);
console.warn('Dropping extensions:', droppedModules);
console.warn('Retrying extensions:', selectedModules);
require(selectedModules,
function () {
handleSuccess(onLoad, arguments);
},
function (error) {
handleError(error, onLoad);
});
return true;
}
}

The retryLoading handler. Demonstrates how the reload a module, if there is an error condition. Only the modules with the prefixes listed in modulesPrefixesToRetry (see above) will be reloaded.

return {
load: function (name, require, onLoad, runtimeConfig) {
if (runtimeConfig.isBuild) {
onLoad();
} else {
var moduleConfig = runtimeConfig.config[name] || {},
modules = moduleConfig.extensions;
if (modules) {
if (!.isArray(modules)) { modules = Array.prototype.concat.apply([], .values(modules));
}
if (modules.length) {
require(modules,
function () {
handleSuccess(onLoad, arguments);
},
function (error) {
if (!retryLoading(require, name, modules, onLoad, error)) {
handleError(error, onLoad);
}
});
} else {
onLoad([]);
}
} else {
onLoad();
}
}
}
};

The main method is simply returned as js object.

All listed modules in the extension point list will be loaded and executed before the callback (the carrier module with the cs-ext entry) will be executed.

This may sound quite theoretical. Lets use cs-ext.

Usage of cs-ext

  • Select the module which you want to amend with an extension point. Lets use the csui/controls/table/cells/cell.factory (MUST exist) as an example.
  • Configure the proper extension in the project json like

  • Open the cell factory and examine the source code.

Notice the csui-ext! line at the end of the define-module list. This will search the require.config entries to get a list of the extension modules for this extension point. All listed modules (here hello.view) will be loaded and executed before the callback (stated in the line csui-ext) will be executed.

Back in the callback , the _.extend function extends the prototype of the cell factory by the methods “hasCellViewByOtherKey” and “getCellView”.

Summary

To make a custom extensible module (with extension point), add the csui-ext requirejs extension to your module and set the modules to be loaded in the appropriate json extension file.

Then point to your extensible module from your widget, and you are done. Then your module is configurable and extendable by using the csui-ext util module.

If you want to extend existing modules, you’ll have to spawn the widgets from the library to reflect your new module.

The famous “define is not defined” Error (or “Mismatched anonymous define modules)

Famous Image Problem

In the content server 20.4 you’ll encounter from time to time a requirejs error “define is not defined”. Normally on defining icons. This is very entertaining.

In 16.2.10 the same thing worked as a charm.

Dont panic, in the “Hitchhikers Guide to the Galaxy” you’ll find the solution.

42 (As always)

(Just kidding. Lets be serious.)

Serious

The case in 16.2.10:

Screenshot in 16.2.x

In 20.2 and above

The same perspective in 20.2 and later

Ups. Looking insane.

Cure

Examine the browser console output. At the debug level.

Browser Console
Browser Console

As a nice addition for the entertainment, the module is uglyfied, it makes no sense to search for this strings, as they are produced during the grunt tasks. But on the other hand, a couple of lines further down there are some complaints of the grid.view.js that the “getSpritePath” is missing. And the offending module is supposed to return the getSpritePath function.

So, a search on getSpritePath gave the offending module, the sprite.js, which was introduced in 20.2 and is obviously required, when a widget wants to display sprites.

The module shows

Original Sprite.js

Lets consult the requirejs error page mentioned in the browser console.

Requirejs Error page

A check of stackoverflow.com gave me the resolution “name collisions can produce this” so I changed the sprite.js to

Changed sprite.js
Changed Sprite.js

Changed the function argument from require to requireReiner. The name doesnt matter.

Result

Everything runs under 20.2 like it used to in previous releases. No more mismatched anonymous define() modules.

But be careful: You’ll get the old js file in all new SDK releases. You should override the old file with the corrected one in all js projects.

As always:

Disclaimer: This works for me. The usage requires proper testing and I will not be liable for any problems whatsoever on that.

System Messages (in the smartUI Welcome Widget)

System Messages in smartUI

Remember the System Messages in the Content Server? This is an handy tool to display system related messages, like: “Next weekend we have maintenance” to inform users on issues with the system.

Normally, System Messages are added or deleted in the Admin pages. Here is an example:

How to add or delete system messages

A name of the Message, the message itself, an option URL for any explanatory pages and an effective date build together the System Message. Per default the System Message has a timeout period of 2 days after publishing, but this can be set in the opentext.ini file by setting a value to NewsDFTExpiration.

From this source the System Messages will be displayed in the legacy gui like this

System Messages are displayed in the legacy gui

But whats if somebody uses smartUI? Unfortunately, there is no possibility to display System Messages in smartUI.

Until the otherwise senseless Welcome Widget is amended. It can look like this:

System Messages in smartUI
System Messages – the new feature in the Welcome Widget.

(Disclaimer: This widget is NOT in the OpenText SDK. This is made by me. Contact me if you interested in using that)

The widget gets its system messages directly from an REST call which extracts this Messages and delivers them to the widget.

The news player is basically an unordered list with an <li> for each news entry. all news were rendered in the <ul> This is a screenshot of the handlebars template.

If any url is in the System Messages, the link opens up in a new tab or a new window.

The news entries scroll with a pure CSS3 animation, no additional Javascript is needed for that. Here is the animation part of the news

And the magic of animation is done with this:

And suddenly the Welcome Widget supports System Messages.

Nice, isn’t it.

Hidden Gems in the smartUI SDK: The side.panel

An overview of the side panel

One of the most interesting controls in the SDK is the side.panel. Reminds somehow to the good Documentum side panels, but is native in the new SDK for Content Server 20.4.

This can be used as a simple control to show things like search forms or oanything you like. Also, multiple views (slides) can be shown in a “Wizard Style”.

First lets take a look on the the sidepanel right out of the box. Quite astonishing, there is a index.html actually working under csui/controls/side.panel/test/index.html. If somebody starts this file, we’ll see side.panel in action:

Shows a nice panel sliding from left/right based on the configuration. This view can be used to show a single view or multiple views (as slides) as per configuration provided to it.

Quite interesting is the fact that if slides provided to the panel, panel’s footer include navigation buttons along with the button provided to the respective slide as part of configuration.

side.panel has modal (dialog) behaviour by default which optionally can pass using constructor param as well (options.modal).

There are several usage possibilities.

Simple Usage (on the right of the screenshot above):

var sidePanel = new SidePanelView({
title: 'Simple Usage Title',
content: new Backbone.View(),
buttons: [{
label: 'Button1'
}]
});
sidePanel.show();

If you want to have several buttons on the footer (in the middle of the screenshot above):

var sidePanel = new SidePanelView({
headerView: new Backbone.View(),
content: new Backbone.View(),
footer: {
leftButtons: [{
label: 'Button1'
}],
rightButtons: [{
label: 'Button2',
id: 'btn2'
}]
});
sidePanel.show();

An example for a “wizard style” sidepanel sliding from the left or the right into the screen

var sidePanel = new SidePanelView({
slides: [{
title: 'Step1',
content: new Backbone.View(),
buttons: [{
label: 'Reset Form',
className: 'binf-btn binf-btn-default'
},
{
label: 'Search',
disabled: true
}]
},
{
title: 'Step2',
content: new Backbone.View(),
buttons: [{
label: 'Finish',
close: true,
className: 'binf-btn binf-btn-primary'
}]
}]
});
sidePanel.show();

There is also a documentation available, at csui/controls/side.panel/doc/side.panel.view.md

Nice, isn’ it?

Happy sliding !

Remove Commands from Nodestable etc in the smartUI SDK

Command is Gone

From time to time you’ll need to remove commands from the widgets, like the nodeslist widget.

The magic spice is setting up a blacklist on the masks.js files during the initial phase:

csui.require.config({
  config: {
    'csui/widgets/search.results/toolbaritems.masks': {
      'mycustomer': {
        'otherToolbar': { blacklist: ['Properties', 'permissions'] },
        'inlineToolbar': { blacklist: ['Properties', 'permissions'] }
      }
    }
  }
})

There are several possibilities to do that.

1, The approved way

The approved way is to configure smartUI before its initialized from OScript.

This can be done by overriding the GetDynamicConfiguration in your base smartUI module (the one with the csuiextension orphan) like:

override function Assoc GetDynamicConfiguration(Object prgCtx, Record request)
  
    List blacklist = { "Copy", "Move" }
    return assoc{
      "csui/widgets/nodestable/toolbaritems.masks": assoc{
        "basecsui": assoc{
          "tableHeaderToolbar": assoc{ "blacklist": blacklist },
          "inlineToolbar": assoc{ "blacklist": blacklist },
        }
      },
      "csui/widgets/nodestable/headermenuitems.masks": assoc{ 
        "basecsui": assoc{ "blacklist": blacklist }     }    }
  end
end

Here in this example, the toolbaritem.masks and the headermenuitem.masks are set up with our magic spice (a blacklist containing all the signatures of the commands not desired). This will remove the “Copy” and “Move” commands from the list of commands permanently. And permanently means, this will survice a Page Reload.

2. The ugly way (but also surviving a Page Reload)

The ugly way is a way is the standard OpenText Way of overriding app.html and configuring the blacklists by yourself. Lets take a look at the app.html (found at ../core/module/csui/html).

Here is an example on a windows server:

Where to find app.html
app.html - the head

In the upper part you can see the csui.require calls. At the top you’ll notice a csui.require.config call, where you can put our magic spice (see above).

The disadvantage is, when you override app.html (directly or by using htmlmap) then you’ll have to check, if any future OpenText patches will override the app.html also.

BUT: If you override app.html, you can take advantage of this for example by implementing a permanent footer, which is always drawn at the bottom. You cannot do that with pure smartUI tools.

Here is an example of a permanent footer in the body part of the app.html.

Multiple usages of app.html - the body

3. The force way

There is also a brutal way to remove commands without that configuration of app.html. This requires

  • a widget or a command to do the removal
  • a couple of js lines

But on the other hand, this is the way which allows easy recovery of the command by doing a simple refresh of the page.

Here is a demo case (a wild version of the hello widget from my training installation). This is a widget with some demos and a new inserted button to delete a command.

a very chaotic demo

Behind the button are some js lines of code, which will remove the Copy-Command. Actually, the lines var b=commands.get(“Copy”); and commands.remove(b); do the job.

You will have to require /csui/utils/commands unter commands to use this two lines.

Two lines to decide the fate of the copy command.
Two Javascript Lines will decide the fate of the copy command

Lets see the initial command set. The Copy Command is here as usual.

Copy command lives

After the red button is pressed in the then the Copy Command is gone:

Copy Command is gone

We simply deleted the Copy command from the list of commands. This means, a simple Refresh will restore it.

Have much fun on playing around with commands!