Welcome to the OPA Hub!


Category Archives: JavaScript Extensions

Template Generator Update – JavaScript for Control Extensions

Template Generator – JavaScript for Control Extensions

Another update, quite a big one, for the template generator. We’ve added lots more information to explain how to use the generator, and hopefully how to work on the template once you have created it. In addition, we have added the Entity Container as a new extension type, so you can create scrollbar-friendly lists of instances for your Entities. Read on for more information. If you just want to download the new version leave a comment and I will send it to you. In the not too distant future we will be releasing it to the OPA Hub Shop, but for now just ask and we can pass it to you.

Control Extension Template Generator : New Form Available

If you don’t intend to use the template code straight away, you can now just print the Form and keep it for later. At the moment the form just dumps the code in plain text, it does not pretty-print it like the screen output, but the code is still ready to copy-and-paste.

Control Extension Template Generator : Information Added

In the Form, we have included some hopefully useful background information about using the code, what to look out for and what to know in terms of where you might want to customize the code. We’ll keep adding to this Form as time goes on, with anything we think might be useful.

Control Extension Template Generator : New Extension

You can now generate Entity Container Extensions. This template requires an extra Property and uses jsGrid to provide a scrolling layout. Again, more information is given in your Form about how to use it and how to customize it to go even further. As always, the official documentation is your friend.

Control Extension Template Generator : Example Container

New Video

And so, to close, you will find below a short video explaining the new Extension Template for Entity Containers, and giving you a bit more background about the different aspects of this Extension type. Nothing beats having a go yourself. Of course, as we always say, the code is entirely for entertainment purposes, never for production, and it’s your own fault if you don’t get a professional to rewrite it. But at least you will know that it can be done, and as a consultant that is often one of the most important things to know.

The video can be viewed here:

Entity Collect Extension

Entity Collect Extension

Some time ago I wrote about Entity Collect Extension and the challenges of writing a demonstration piece of code. The challenges of Entity Collect Extension are pretty well known, but here is a run down of the most important one:

  • You must build the container and the contents,  and manage them

That means, that if you build an Entity Collect Extension, you cannot use other control extensions inside it :- you must code the entire contents yourself, so you would be looking at

  • Handling all different data types of attribute
  • Handling all the basic events of these attributes
  • Managing instance creation and deletion
  • Handling styling options and look and feel

So when you look at this shopping list, it can be quite daunting. Even so, I said to myself, if Oracle provides such a functionality, then somebody somewhere is going to use it. And so the idea came to create a demonstration Entity Collection Extension. When I started working on it I really did not have much time to look at it, so I wrote a couple of articles about my experiences and left it at that.

Recently I have been revisiting the concept again, and have found  time to work on it a little bit more. I added it to the OPA Hub Shop (on the strict understanding, as usual, that it is completely for educational and amusement purposes only).

That statement is particularly important in this case. I only decided to do this because I am fascinated by other people’s JavaScript frameworks. I find it useful to know what goes on underneath the glossy Oracle Policy Modeling HTML output. And my example is basic to the point of being little more than a sandbox (oh, and by the way, it still has a lot of issues – especially when you are running it in the Debugger rather than the Browser).

Entity Collect Extension in JavaScript

This version tries to cover off the 4 shopping list items shown above, and adds a couple of interesting ideas

  • Dynamic Delete Button (remove the button based on an attribute value). This is one request I have seen many times – the ability to forbid deleting in certain circumstances.
  • Handling Date Time and Value Lists for display and data entry.

I still have to find time to investigate :

  • Handling Inferred attributes that need to be refreshed as you are entering instance attributes.

I’ve just about had enough of this now so I am going to leave it for a while.  It has started to make my head spin.  Nonetheless it is an interesting exercise and helped make clear how cool the out of the box JavaScript really is.

The silent movie below shows where I’m at. All that work, for this rather dull looking thing. Sometimes there is not much to show for efforts. Of course, if I was a real programmer, I would be doing all of this in a much more efficient way (avoiding complete page refreshes at every change and so on) but I found this exercise very interesting. Certainly it gives me a better understanding of the scale of such a task.

Have a nice day!

Showing a Loading Image During Entity Creation

Showing a Loading Image During Entity Creation

When a user is entering some information into Entity attributes, it is entirely possible that one of those entity attributes may take its information from a Search extension. For example, you are entering instances of the Person entity and each Person has a location, so you want to select the location using a Search extension.

The Search, given that it is perhaps an Ajax call, could take some time. So you want to signal to the user that there is nothing to worry about, but they need to wait. Typically this is done through some sort of icon or image being displayed, much in the style of the Windows egg-timer or similar. This probably will also need a CSS style rule or two, in order to make it a bit funky.

We want to make sure that this is displayed in the right place, even if the user is creating several instances of the same entity. I mean that the icon should be displayed in the correct area of the screen, especially if you have instances whose screen layout takes up some space.

Anyway as always a picture is worth a thousand words. Here is the instance collection form:

Showing a Loading Image During Entity CreationWhen you have several on the screen, it might look like this:

Showing a Loading Image During Entity Creation

The Destination attribute is a Search extension that helps the user search for a Train Station in the United Kingdom. It take a few seconds for the search to happen.

So our timer needs to be shown in the right place whenever the user is searching. It needs to be instance A or B for example, depending on the instance the user is working on.

Showing a Loading Image During Entity Creation

In the example above the user has typed the Search criteria. The loader is shown in the centre of the instance while the search is happening. So we are Showing a Loading Image During Entity Creation.

Showing a Loading Image During Entity Creation

When the search data is returned, as in the example above, the user should no longer see the loader and the operation can continue as normal.

If the user moves to another instance, then the process should start again but the loader should be instance-aware and show in the correct place so as not to confuse.

Showing a Loading Image During Entity CreationTo do this we can use the Search extension, and add a little bit of extra code to

  • Check to see if we have already displayed the special icon
  •  If we have not, create it, center it on the instance we are working on, show it and make the Search
  • If the icon already exists, move it to the correct instance and show it then make the Search
  • When the search data is returned, hide the icon until the next time.

This example will work with non-tabular forms. I’ll be back with a second post investigating them in a couple of days.

You can find this simple example (with all the usual caveats and reminders that this is just for fun) in the OPA Hub Shop.  The official documentation is here, as always. Thanks to Shankar for the great example of Showing a Loading Image During Entity Creation!

Siebel CRM as a custom Search source

Siebel CRM as a custom Search source

This post is inspired by a conversation I’ve been having over the last few days with another OPA consultant (thanks Prashil!) . Although as it turned out, the requirement had nothing to do with Siebel (that will teach me to not assume anything!), the concept of making REST calls to a CRM or CRM-like data source has been on my mind. But how can I use Siebel CRM as a custom Search source?

In this example, we will use Siebel 2018 as the source of a custom Search box. Along the way we will see how the Siebel CRM REST API sends us data and what we can do with it. At the same time, we will indulge in some trickery to not show everything we have in our Search results to the user. It will mean we create two JavaScript extensions, a Search and a Full Input.

Firstly, the Siebel 2018 instance in question is using the standard REST API, and it is the standard Component called Account which we will be querying. In many public services, Account is used to store partner organizations, external suppliers and so on. It is a very common component. The base URL for the REST calls in my case will be something like the following

https://XXXX:9001/siebel/v1.0/data/Account/Account/?fields=Name,Location&?ChildLinks=None&searchspec=([Name] LIKE '"

There are three things to note here.

Firstly I am only interested in two fields (the third field I need, Id, is actually going to be included automatically anyway).

Secondly I am using a Search Specification with Siebel standard syntax to search using the Name of the Account. So if I type “ABC”, it will look for Accounts starting with ABC.

And finally, the URL string needs to be capped with the following to finish it “*’)” so that there is a wildcard search for ABC Inc, ABC Corp. and so on. The URL also includes an argument regarding child links in the output to reduce volume.

Siebel CRM as a custom Search source

The information returned in a standard output will consist of a series of data.items. So we can iterate over the data.items and for each item, we can get the Item.Name, Item.Location and Item.Id. Since Siebel paginates its output, we are actually only going to get a maximum of ten records unless we add another URL argument and make further calls to Siebel (to get page 2, page 3 and so on). But for a query result, a ceiling of 10 is pretty good for Siebel CRM as a custom Search source.

As a side note, this example – you have noticed – is using the Siebel REST API in its unvarnished, naked form. Obviously you would do well to control / restrict access and authenticate consumers in real life. We’ve seen in previous examples that we can pass headers in our Ajax call when Oracle Policy Automation asks for data from a Search source.

In the Commit callback we will update three attributes with the values of the Siebel Fields I just mentioned. Now, at the moment, if you want to update an Oracle Policy Automation Attribute in a JavaScript extension, that attribute needs to be on the active Screen for it to work. So what happens if you don’t want to show that value to the end user, but you still want to capture it for future use in your rules?

One approach (which I am using for demonstration purposes only you understand, as usual) will be to create an invisible Input, so that we can add our data to the Screen without the user seeing it. To do this you might use a fullCustomInput extension. This is different from the customInput, because it manages the Question Text and the Input control. So we can place it on our page and format the whole thing – even perhaps make it disappear.

Siebel CRM as a custom Search sourceThe two examples working together are shown in the video below, and I have added a more appropriate fullCustomInput example, as well as the Siebel customSearch example, to the OPA Hub Shop. I am also in the process of adding them to the Template Generator, so you will be able to generate a fullCustomInput and a sample Siebel customSearch yourself as well.

Have fun with Siebel CRM as a custom Search source, and as always the official documentation is your guide.

Travel Compensation : JavaScript Extensions

Travel Compensation : JavaScript Extensions

Many of our readers will be familiar with the Example Projects (which include Travel Compensation)  that are provided with the download of Oracle Policy Modeler. If you are not, they are accessible here:

OPA 12 - Travel Compensation Example Access

If you are not familiar with them, we encourage you to dive right in and to find out about all the wonderful examples you can find in there. It is a great learning tool and a good way to discover potential use cases. One of the more famous ones is the Project related to the legislation relating to Travel Compensation by Airlines, in the European Union (EU261/2004), mentioned above.

This allows the traveler to receive a compensation amount when their flight is delayed or they are refused boarding (among various criteria)  if the flight meets certain conditions (there are various exclusions for territories such as Gibraltar and so on).

The Project

The provided example Project has a number of key learning points :

  1. The project has multiple translation files
  2. The project is mapped to a RightNow Connection
  3. The project uses the CurrentLocale() functions introduced in 18C
  4. It uses a number of Excel tables to maintain static data.
  5. It links to various websites for example to calculate distances.

The existence of Translation files is a good chance for new started to discover how multiple interfaces are built inside Oracle Policy Automation 12, and the mapping to RightNow has two side effects (even if you do not have access to the RightNow instance specified in the Connection).

OPA 12 - Travel Compensation Example RightNow Dialog

Firstly if you have never seen the RightNow-specific (as opposed to the generic Web Service Connection dialog) window, it can come as a bit of a shock. If you need a primer as to what the different icons mean, you can check out our series about Service Cloud (RightNow) and OPA. The second side effect is the long set of Value Lists that are drawn down from Service Cloud as part of the Connection (even if they are not being used here).

OPA 12 - Travel Compensation Example Value Lists

We mentioned the arrival of locale-detection functions in our What’s New post a few weeks ago. The two most interesting things, and the point of this post, is the fact that Excel is used to store static data (in the case below, airline names and countries)

OPA 12 - Travel Compensation Example Excel Sheet

and that some of the information to be entered is referenced using URLs : in the case below, the need to calculate a distance between two airports:

JavaScript Extensions : Airports, Airlines and Great Circle Mapping for Travel Compensation

In the example Project, the focus is on a clear definition of the Policy and a demonstration of how to implement a good design pattern. But the end user experience suffers a bit – this is not a criticism, since it obviously was not the learning focus – because of the kind of data to be entered.

Take for example the first screen, where we enter our journey details : departure and arrival airports. Given that the airport information is extremely useful (namely, every airport has an ICAO code, and a latitude and longitude), we are going to use a custom Search to let the user find the airport and we will capture some extra information : the Country and the ICAO code. The Country is used later in the rules, and the ICAO code will come in very handy in a moment.

OPA 12 - Travel Compensation JavaScript Search Extension Airports

We’ve actually two versions. The first version uses a website called http://geonames.org : they have a variety of free (registration required) web services for searching for places including airports. It does not have ICAO codes but has a lot of other information. The second version uses a freemium web service from https://market.mashape.com/marcusgoede/great-circle-mapper/ which includes an airport search which additionally returns an ICAO code. Both of them return the Country.

A later page asks for the name of the Airline : again we decided to use a custom Search, from a website called https://aviation-edge.com which has a variety of web services including an Airline lookup which includes the operating country (which is referenced in the rules).

OPA 12 - Travel Compensation JavaScript Search Extension AirlinesFinally, the legislation bases compensation in part on the kilometer distance of the flight. It must be calculated using the Great Circle method according to the law, this method takes into account the curvature of the earth. We returned to the freemium web service listed above to take advantage of the airport to airport Great Circle mapping Web Service, which also can return duration (based on a supplied average airspeed) and many other nuggets of information.

OPA 12 - Travel Compensation JavaScript Label Extension Distance

For the above example we use a custom Label (which is not displayed) which drops the calculation into the Input box so the user can adjust it if required (but our tests proved it to be very accurate indeed).

As such, these three extensions increase the data entry speed and make the process much simpler. So there you have it, some examples of useful JavaScript extensions. The Project now looks like this:

You can find them in the OPA Hub Shop as usual, search for Travel Compensation. Don’t forget the official Oracle Policy Automation Developer Guide Interview Extensions Reference.

Temporal Reasoning #5 : Temporal Attributes in Interviews

Temporal Reasoning #5 : Temporal Attributes in Interviews

In the final part of this mini-series, the OPA Hub Website continues to look at Temporal Reasoning and in this particular chapter discusses the display of Temporal Attributes data in the Interview experience.

If you missed any of the previous parts of the series, they are here:

So now that the we have a bit of understanding of how these data elements work, what about displaying them in a good way to the end user in the Interview. Well, part of the answer is hidden in part four of this series. We cannot actually display temporal attributes for data entry in an Interview (so conversion comes in very handy).

Let’s be more specific. Using the project from the previous chapter, in 18C, when an attempt is made to display the temporal information on a Screen, various things happen that underline the some important concepts:

Temporal Attributes in Interviews Animation OPA 12Please excuse the retro-style animated GIF above. But the demonstration above illustrates the fact that Temporal attributes and their change-points are complex data types that cannot be handled in a “normal” way. The one exception to the above is if you have a Temporal attribute whose values are the Goal of the interview, then an Explanation will display the data in a coherent way:

OPA 12 - Viewing Temporal Attributes in Interviews

If your project is using RuleScript and your data is pre-seeded, then potentially you could access it by deriving a string value which is a concatenation of the different values and displaying that attribute using a label control.

// RuleScript(myString) <- (temporalBankBalance)
function FindHighest(global) {
	console.log("Starting RuleScript");
	var v = global.temporalBankBalance;
 
		console.log("Base Value of v " + v._baseValue);
		var idx,
		maxVal = null;
		var myString = "";
		console.log("Length of Temporal Array " + v._changeValues.length);
 
	if (v._changeValues.length <= 0) {
		global.myString = "No Temporal Values";
	} else {
		console.log("Getting Temporal Values");
		for (idx = 0; idx < v._changeValues.length; idx++) { var changeValue = v._changeValues.valueAt(idx); if (changeValue != null && (maxVal == null || changeValue > maxVal))
				maxVal = changeValue;
		}
		global.myString = global.myString + changeValue + ";";
	}
 
}

But given that RuleScript is experimental, that it’s use cases are highly controlled this would be a very bad idea. Plus it would only work if the temporal values were pre-seeded into the Interview, which renders it all very complex.

So what is plan B? It might be to use something like the Entity Container Extension that we have previously looked at (which would imply using the conversion technique mentioned in part four).

If you are looking for a quick and dirty way to get at the Temporal values, even though the JavaScript Extensions do not actually support them today, the values are still accessible. They can be accessed using something like this. I have not published this as a download since the snippet below is very primitive.

 

/**
 * Richard Napier The OPA Hub Website August 2018
 * Educational Example of Custom Container with a Timeline inside
 * I will remember this is for demonstration and educational purposes only
 */
OraclePolicyAutomation.AddExtension({
	customLabel: function (control, interview) {
		if (control.getProperty("name") === "xTimeline") {
 
			return {
				mount: function (el) {
					var script_tag_addition = document.createElement('script');
					script_tag_addition.setAttribute('src', '${resources-root}/js/timeline.min.js');
					script_tag_addition.setAttribute('type', 'text/javascript');
					document.getElementsByTagName('head')[0].appendChild(script_tag_addition);
					var stylesheet_tag_addition = document.createElement('link');
					stylesheet_tag_addition.setAttribute('href', '${resources-root}/css/timeline.min.css');
					stylesheet_tag_addition.setAttribute('rel', 'stylesheet');
					stylesheet_tag_addition.setAttribute('type', 'text/css');
					document.getElementsByTagName('head')[0].appendChild(stylesheet_tag_addition);
 
					var myDiv = document.createElement("div");
					myDiv.setAttribute("class", "timeline");
										myDiv.setAttribute("data-mode", "horizontal");
					el.appendChild(myDiv);
 
 
					var myDivWrap = document.createElement("div");
					myDivWrap.setAttribute("class", "timeline__wrap");
					$(".timeline").append(myDivWrap);
 
					var myDivChild = document.createElement("div");
					myDivChild.setAttribute("class", "timeline__items");
					$(".timeline__wrap").append(myDivChild);
 
					// Don't do this, it relies upon the temporal attribute
					// being the only one in Global exposed on the page as a %label%
					var myTemporal = []
					myTemporal = control._source.screen.config.data[0].instances[0].attributes[0].value.changePoints
						for (var i in myTemporal) {
							var iterateDIV = document.createElement("div");
							iterateDIV.setAttribute("class", "timeline__item");
							iterateDIV.setAttribute("id", i);
							$(".timeline__items").append(iterateDIV)
							var iterateDIVContent = document.createElement("div");
							iterateDIVContent.setAttribute("class", "timeline__content");
							$('.timeline__item[id="' + i + '"]').append( "GBP "  + myTemporal[i].value + " on " + myTemporal[i].date)
						}
				},
				update: function (el) {},
				unmount: function (el) {
					var myDiv = $(".timeline");
					myDiv.remove();
 
				}
 
			}
		}
	}
});

The above snippet relies upon a jQuery plugin to display the data. This gives something like this, a visual timeline on the left of this page:

Temporal Attributes in Interviews JavaScript Extension

Of course there are hundreds of Timeline plugins, each more sophisticated than the other, on the Internet.

We hope that this series has brought to light some of the key features of temporal reasoning, and thanks to Orlando who suggested this series in the first place. Have a good day and see you soon!

 

Detail Pop-up in Oracle Policy Automation

Detail Pop-up in Oracle Policy Automation

The other day someone came to me with a curious and interesting problem. They had a number of entity instances, inferred in an Excel spreadsheet. These had to be displayed in the usual way with an Entity Container in a Screen of Oracle Policy Modeller. So far so good, I hear you say.

Detail Pop-up in Oracle Policy Automation 1

The inferred attributes (which in the end would probably be coming from a data source, but for now come from Excel as inferred instances) included a Text attribute that was frankly far too large to display correctly in the Screen, given that there might be a few rows of instances in the final result.

We experimented with lots of different layouts, dynamically hiding and showing items based on various criteria in order to make room, but in the end we came to the conclusion that we needed some sort of Detail Pop-up in Oracle Policy Automation – something that could be called upon by the user as and when they needed it, but ignored (and invisible) when not needed.

Here is the starting point for our adventure.

The Screen above is populated with all the instances of the student’s scholarship. On the left is a set of information that we need to display on request. Normally we will only display the name of the Scholarship. You will see in the list of attributes there is an overview ( a text attribute), a deduction ( a currency attribute) and a renewable status (a boolean attribute). There are a few others, including the contact details (a text attribute, which is a URL).

So we are going to customise the label control I have just described. It is “inside” the Entity instance loop : so in reality there will be one per instance. We need our label to contain, as you would expect, the correct information. We wish to avoid pop-ups (nasty!) and dialogs (too complex for a simple window) and tool-tips are too small and simple for the data we have. The label shown will have a custom property called “name” and will be used as a hook for our JavaScript Extension.

We experimented with all sort of things before we went for this option : JavaScript is a last resort. We were frustrated by the behaviour of hidden items that appeared slowly (we could see “uncertain” appearing before the out of the box JavaScript populated the bound controls). So it was going to be JavaScript.

So,  our Detail Pop-up in Oracle Policy Automation needs to meet these challenges. We are going, as a simple demonstration, to use a CSS toggle to show or hide the relevant data for our instances. We can set the scene as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.area {
position:relative;
color:#0645AD;
font-weight:400;
}
 
.area:hover {
text-decoration:underline;
text-decoration-color:blue;
cursor: pointer;
}
 
.fixed {
position:absolute;
top:190px;
left:465px;
border:0;
z-index:9999;
background-color:#FFF;
display:none;
height:300px;
width:420px;
float:right;
text-decoration:none;
text-decoration-color:#000;
text-color:#000;
padding:5px;
}

The above CSS file sets up two main classes and a pseudo-class for a mouse hovering over our row. The area is the area we will normally show – with just the name – and the fixed area is a fixed DIV which will display (or not) when we decide we want to visualise the information. Now for the main content of our customLabel extension. Here is the mount key with as usual, my simplistic attempts at coding : for the umpteenth time I’m not a professional – but my job is to show something can be done, and let other’s get on with making it happen.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
 
if (control.getProperty("name") == "xLabel") {
return {
mount: function (el) {
var maindiv = document.createElement("div");
maindiv.style.visibility = 'visible';
maindiv.innerHTML = interview.getValue("scholarship_award", "scholarship", control.instance);
maindiv.classList.add("area");
maindiv.setAttribute("id", interview.getValue("scholarship_award", "scholarship", control.instance));
el.appendChild(maindiv);
 
var tooltipdiv = document.createElement("div");
tooltipdiv.style.visibility = 'visible';
tooltipdiv.classList.add("fixed");
tooltipdiv.innerHTML = control.getCaption();
tooltipdiv.setAttribute("id", interview.getValue("scholarship_award", "scholarship", control.instance));
el.appendChild(tooltipdiv);
 
$("div [id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").click(function () {
$(".fixed").hide();
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").html("<h6>Name : " + interview.getValue("scholarship_award", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6>Overview : " + interview.getValue("scholarship_overview", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6><b>Renewable</b>: " + interview.getValue("scholarship_renewable", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6><b>Maximum Value</b>: " + interview.getValue("scholarship_deduction", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6><b>Eligibility</b>: " + interview.getValue("scholarship_eligibility", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6><b>Minimum Grade</b>: " + interview.getValue("scholarship_min_grade", "scholarship", control.instance) + "</h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").append("<h6><b>Contact</b>: <a href='" + interview.getValue("scholarship_contact", "scholarship", control.instance) + "' target='_blank'>SFAS Office</a></h6>");
$(".fixed[id='" + interview.getValue("scholarship_award", "scholarship", control.instance) + "']").toggle();
});
 
}

Here is the review of the Detail Pop-up in Oracle Policy Automation code shown above, starting with the usual check to make sure we are only working with our label and not any other label on the Screen. In lines 6 to 11 we add a new DIV (to replace the one that contained all those %substitution%s , and we populate it with only one attribute. Since that attribute is also unique, we use it as a handy way to populate the HTML id attribute.

In lines 13 to 18 we create a second, hidden DIV that uses the fixed class shown above.

In lines 20 to 29 we set up the click event so that the user can click on the label and the hidden text will be revealed. The code preview (I notice) has eaten the ending part of the line, so use the PDF version instead. Notice the use of getValue, with the entity name and the instance, to ensure that we create a DIV with a unique name and unique content. The content will be toggled (hidden or shown) when you click on it.

Finally the unmount is very standard, cleaning up our various pieces by removing them.

1
2
3
4
if (control.getProperty("name") == "xLabel") {
$(".area").remove();
$(".fixed").remove();
}

The end result looks like this, before the click:

Detail Pop-up in Oracle Policy Automation 3And after the click:

Detail Pop-up in Oracle Policy Automation 4

Our Detail Pop-up in Oracle Policy Automation prototype gives the user the information they need when they need it. Of course it can be extended and transformed into something much less ugly, but this is a good start. You can find the PDF in the Shop, it’s free!

What’s New in Oracle Policy Automation 18B #2 Relationship Control Extensions

What’s New in Oracle Policy Automation 18B #2

The main thrust of this post first came into my head when I was writing one of the recent Back to Basics posts about Relationships. And as if by magic, Oracle Policy Automation went ahead and improved the product with something I felt was lacking. I should ruminate more often, perhaps they have telepathic powers over there. So in this post, What’s New in Oracle Policy Automation 18B #2, we are going to look at the new feature of the Control Extensions : the ability to customise the Relationship experience.

What’s New in Oracle Policy Automation 18B #2

The relationship above is a good example. In the course of a prototype, I designed the car and the passenger entities for a car-sharing enterprise. A car can have many potential passengers. For each journey, however, your passenger can only be in one car at a time. And yes, I understand that I could build a many-to-many and intersection the car and passengers or infer the current passengers or what have you, but this is just an example.

What’s New in Oracle Policy Automation 18B #2

So in the above example, you can see that I am in the process of selecting the passengers for each car. Putting aside the discussion about how best to model the data, there is a challenge here. The checkbox (which is the only display offered) is fine, but due to the lack of dynamism (?) in the display, the choices remain static. I mean by that you are able to choose an incoherent selection, with the same passenger being in multiple cars.

Of course, when you do so, the engine (correctly) gives you an error and you must correct your data entry. But what if we did it another way?

The core of this is the fact that now, in Oracle Policy Automation 18B, you can use the following in your Extensions:

control.getControlType() – which now will return “OneToMany” or “ManyToMany” and so forth for relationship controls. So your code could adapt the User Experience based on the cardinality.

control.getOptions() – returns an array of the different choices for the user ( the passengers in my case above). So you can retrieve the list of choices.

To help manage this kind of extension, control.getValue() returns an array of the selected values for your relationship (the instances that have been selected). So you can examine the selected values.

Let’s look at this code. It is, as always provided for educational and entertainment purposes (indeed, many will find my stream of consciousness code amusing). It is also available on the OPA Hub Website Shop page as a free PDF download. So let’s see What’s New in Oracle Policy Automation 18B #2 : Relationship Controls with an example.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
(c) 2018 Richard Napier The OPA Hub Website May 2018
Educational Example of Relationship Input Controls
I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xPassengerSelect") {
			return {
				mount: function (el) {
					//console.log("Control " + control.getProperty("name") + " is a " + control.getDataType() + ", originally a " + control.getControlType());
					var myValues = [];
					//Previous values
					myValues = control.getValue();
					var myOptions = control.getOptions();
					//console.log("Obtained list of instances for control " + control.id);
					var myDropDown = document.createElement('select');
					myDropDown.setAttribute('id', control.instance.toString());
					myDropDown.setAttribute('data-instance', control.instance.toString());
					myDropDown.setAttribute('data-entity', control.entity.toString());
					myDropDown.setAttribute('multiple', 'true');
					for (j = 0; j < myOptions.length; j++) {
						var myoption = new Option(myOptions[j].text, myOptions[j].value)
							myoption.setAttribute("data-instance", control.instance.toString());
						myoption.setAttribute("data-entity", control.entity.toString());
						myDropDown.options.add(myoption)
						//console.log("Added list option " + myOptions[j].text);
					}
					for (i = 0; i < myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected");
						}
 
					}
					$(myDropDown).change(function () {
 
						//New Values Selected
 
						for (i = 0; i < myDropDown.length; i++) {
							currentOption = myDropDown[i];
 
							if (currentOption.selected == true) {
								myValues.push(currentOption.value);
 
								//Disable All Values Matching Selected in other instances
								$("select [data-instance!='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("disabled", "true")
 
							} 
 
						}
					});
					var deselectbutton = document.createElement("button");
					deselectbutton.setAttribute("type", "button");
					deselectbutton.setAttribute('data-instance', control.instance.toString());
					var deselectbuttontext = document.createTextNode("Deselect All");
					deselectbutton.appendChild(deselectbuttontext);
 
					el.appendChild(myDropDown);
					$(myDropDown).after(deselectbutton);
 
					$(deselectbutton).click(
 
						function () {
						$("select [data-instance='" + this.getAttribute('data-instance') + "']").filter(":selected").prop("selected", false);
						control.setValue("");
							$("select [data-instance!='" + this.getAttribute('data-instance') + "']").attr("disabled", false);
					});
 
					for (i = 0; i < myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected")
 
						}
 
					}
				},
				update: function (el) {},
				unmount: function (el) {}
			}
		}
	}
});

So what are we looking at. There are probably four key areas in this rough prototype.

Lines 18 to 27 build a multiple-select drop-down instead of the check-boxes. Using HTML 5 data attributes, each option and each drop-down (there will be  drop-downs, one for each of the car ) is tagged with the instance name and the entity name. This is useful if you intend to have a page with lots of entity-related things on it , and it was useful in the Entity Collect example from a few weeks ago as well.

Lines  29 to 33 look through the existing values of the Control (maybe the user has already been working on this page, and has now come back to it for further editing) and selects programatically all those values that were chosen previously. Otherwise when you click the Next button and then the Previous button, you will no longer “see” your selections even though they actually have been selected.

Lines 38 to 58 handle the Change event if the user selects other items in the multi-select, and ensures that the corresponding items are deactivated in the other drop-downs.

Lines 58 to 78 create the Deselect All button for each drop-down, which removes all the selected items both from the drop-down and from the underlying control values, and re-enables the values in the other drop-downs.

Once again, I state for the record that this was just a “stream of consciousness” which became a bare-bones prototype. There are lots of holes in the code, and lots of repetition because I just wrote it in a single shot. So you have been warned.

It does, however, demonstrate the new functionality, so our post title What’s New in Oracle Policy Automation 18B #2 is fulfilled. This is something you could not really do in previous versions.


Have fun!

Custom Entity Collect Extension in Oracle Policy Automation #1

Custom Entity Collect Extension in Oracle Policy Automation

The idea behind this post, as is often the case, came from a conversation with a customer about something unrelated to the actual result. Suffice to say we were discussing data collection in Oracle Policy Automation and the idea of Custom Entity Collect Extension in Oracle Policy Automation came up, vaguely. The difficulty with demonstrating such an Extension is that every situation will be different, and every extension will have lots of styling to “make it look like something different”.

Perhaps the most important thing therefore is to demonstrate a Custom Entity Collect Extension in Oracle Policy Automation without any custom functionality and without any styling, so you can use it as the basis for your own discovery sessions. Of course, as always (and in particular in this case, as the example is necessarily longer than most), the code is totally for prototype and demonstration purposes only, and I will leave it to you to take the ideas and run with them.

Custom Entity Collect Extension in Oracle Policy Automation Result Final

Alright let’s get started. The Project looks like the following screenshot; namely a single entity called the accident and a variety of input attributes. There are no rules in this Project at the moment.

Custom Entity Collect Extension in Oracle Policy Automation Result 1

The screenshot shows a number of things we will need to think about:

  1. The code will try to be generic
  2. The code needs to read Screen items like the text here
  3. The code needs to offer deletion of instances as well
  4. The code needs to display Boolean data as well as text or numbers
  5. The code needs to display dates with a date picker

The Project also has, for completeness’ sake, an entity container on the final Screen to review the data to make sure that what the user has done has been saved correctly. Of course, you can also check the Data tab in the debugger.

The basic principle of the code is common to all the different examples seen around the Web, namely the Entity Collect has a custom Property whose name identifies it to the JavaScript extension code. I won’t include it here but you can find it in the PDF version at the end of this series.

NOTE : The Code Viewer on this website eats some characters, so be careful (especially less than and greater than symbols)

Getting Started : Make a Container

The first part of our mouncode will build the infrastructure for our container. Fittingly enough, it will be a DIV.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
return {
				mount: function (el) {
 
					// ADD ROW BUTTON THE TOP OF THE ELEMENT
					var button = document.createElement("BUTTON");
					button.setAttribute("type", "button");
					var buttontext = document.createTextNode(control.getAddButtonText());
					button.appendChild(buttontext);
					$(button).click(function () {
						control.addNewRow();
						drawrows();
					});
					el.appendChild(button);
 
					//CREATE DIV CONTAINER FOR ENTITY COLLECT
					var div = document.createElement("div");
					div.id = "entitycollector";
					el.appendChild(div);

As you can see, there was a little more than just a DIV. The code added an “Add Row” Button to the top of the Container, add set a click event to add a row to the Control with control.addNewRow(). The rest of the code adds the button to the page, and then adds an empty DIV.

1
2
3
4
5
6
7
8
9
10
11
12
var myattributelist = control._source.config.templateControl.controls
					function drawrows() {
						$('#entitycollector').empty();
						// CREATE AN ARRAY OF LABELS FROM THE ATTRIBUTES
						var mylabels = [];
 
						for (i = 0; i < myattributelist.length; i++) {
							mylabels.push({
								caption: myattributelist[i].caption.toString(),
								name: myattributelist[i].attributeId.toString()
							});
						}

The code above gets a reference to the list of attributes that are on the Control (essentially, what the designer has added to the Screen in Oracle Policy Modelling. Then it creates an array of label texts for each attribute. This set of labels will be used in the next part of the code. The function drawrows() will perform almost all of the setup of the control.

1
2
3
4
5
6
7
8
9
10
11
12
var myrecords = control.getRows();
 
						if (myrecords.length > 0) {
							for (i = 0; i < myrecords.length; i++) {
								// CREATE A CONTAINING DIV FOR EACH ROW
 
								var rowdiv = document.createElement("div");
								rowdiv.id = "rowcontainer" + i.toString();
								rowdiv.setAttribute('data-rownumber', i.toString());
								rowdiv.setAttribute('style', 'background-color: lightblue;');
								rowdiv.setAttribute('data-instancename', myrecords[i][0].instance.toString());
								$("#entitycollector").append(rowdiv);

This section creates a new DIV for each row of the “records” or instances of the entity. The rowdiv also uses HTML attributes to store useful information about the row such as the instance name, which makes it easy to find things later on either in the HTML source or in jQuery.

Drawing the Inputs

The final part of the code for today looks at drawing the input boxes, check-boxes and other data entry items.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var attrLabel = document.createElement('label');
// FOR EACH LABEL
for (j = 0; j < mylabels.length; j++) {
var myId = myrecords[i][j].id.toString();
var attrLabel = document.createElement('label');
attrLabel.setAttribute('for', myId)
var attrLabelTextNode = document.createTextNode(mylabels[j].caption);
attrLabel.appendChild(attrLabelTextNode);
 
//ADD PROPERTIES TO THE HTML INPUT
var myattributedatatype = myrecords[i][j]._source.config.dataType;
 
switch (myattributedatatype) {
 
case "boolean":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'checkbox');
break;
 
case "number":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'number');
break;
 
case "text":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'input');
attrInput.setAttribute('data-datepicker', 'false');
break;
 
case "date":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'input');
attrInput.setAttribute('data-datepicker', 'true');
break;
 
}

So what is happening here? In the first part of the code, we are setting up the labels by adding the text node to build the appropriate UI. Then we switch through a variety of different data types – note that we have not covered them all, just the core types – and how they will be built in HTML. The date type, for example, is going to use jQuery UI date picker so the type is set to input not date as you might have thought (to take advantage of modern browser support for that input type) but the support is patchy and the limitations many. So it is going to be a simple input but with a jQuery UI element bound to it.

The Boolean uses a check-box and the Number uses number : so we can experiment with that UI experience.

Continues in part two of our Custom Entity Collect Extension in Oracle Policy Automation investigation. If you are looking for more information, the official documentation is to be found here.

Oracle Policy Automation Embed Website in Interview End

Oracle Policy Automation Embed Website in Interview

Oracle Policy Automation Embed Website in Interview

This request comes up quite often, at least often enough that I feel the need to mention it today. The example we are going to use is to embed the OPA Hub Website in an Oracle Policy Automation Interview. In addition we are going to pass an attribute to the website so that it performs a search for us. So, let us start our tutorial “Oracle Policy Automation Embed Website in Interview”.

Now, I am sure many of you are old enough to have spent years trying to avoid IFRAME integrations in applications : Siebel, SAP, they all do it or have done it at some point in time, and they are awful for the most part – whether it be from an accessibility, SEO, browser restriction or other perspective. So here are our goals for this mission:

  • Don’t use an IFRAME
  • Add the Website in a way that does not destroy the look and feel of the Interview
  • The Website must actually function properly

The steps to create this Project are shown below. You should be aware (and not be surprised) that this will not work well in the built-in embedded Browser in Debug Mode, so run Debug mode using Ctrl+Debug or deploy the Project to see the final results.

Oracle Policy Automation Embed Website in Interview Pre-requisites:

A New Project called “Oracle Policy Automation Embed Website in Interview” or something shorter.

Create a global attribute with the text the subject with a name of subject.

Create a new Screen to ask what is the subject. I suggest a Drop-down list with the Values “Siebel Integration, JavaScript Extensions,Service Cloud”.

Create a second Screen to display the Website.

  1. Create a label, using the name  of  the subject to display the chosen subject.
  2. Place this inside a Container
  3. Make sure you add a Property for the Container, naming the Object.

By now the Screen should look like this:

Oracle Policy Automation Embed Website in Interview Design

Now we come to the code. This is quite simple,although we will also need some CSS to make it look right. Add a JavaScript file and a CSS file to your resources folder for this Project. The explanation is after this code, which is as always provided for educational and investigative purposes only:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * Richard Napier The OPA Hub Website April 2018
 * Educational Example of Custom Container with a Website inside
 * I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customContainer: function (control,interview) {
		if (control.getProperty("name") === "xWebsite") {
 
			return {
				mount: function (el) {
					var myDiv = document.createElement("div");
					myDiv.setAttribute("id", "mySpecialDIV");
					document.body.appendChild(myDiv);
					$("#mySpecialDIV").width(900);
					$("#mySpecialDIV").height(600);
					var mySubject = interview.getValue("subject");
					$("#mySpecialDIV").html('XXXXXX'+ mySubject + '">');
				},
				update: function (el) {},
				unmount: function (el) {
					var myDiv = $("#mySpecialDIV");
					myDiv.remove();
 
				}
 
			}
		}
	}
});

Oracle Policy Automation Embed Website in Interview Code

In the code above, here are the salient points.

Lines 13 to 17 create a DIV and insert it into DOM, appending it to the body of the document.

Line 18 retrieves the value selected by the user on the previous page that is present in the Container as a label.

Line 19 is the most important one. Notice the “XXXXX”. Replace this with the website and any URL construct you need. For example, replace it with the following:

<object data="https://theopahub.com/main/?s=

The code viewer didn’t correctly display that part. Insert it exactly as shown, so that you are concatenating the URL with the user selected subject. The key point here is the use of the object tag rather than an nasty IFRAME. Thanks to Stackoverflow!

The rest of the code just tidies up when the unmount happens.

Oracle Policy Automation Embed Website in Interview CSS

The CSS is quite important here, to ensure that the embedding is seamless. Add this CSS code to your CSS file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
object {
    height: 100%;
    width: 100%;
}
#mySpecialDIV {
	float: left;
    margin: 0px;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	background-color: #404040;
}
html
{
    border: 0px;
    margin: 0px;
    overflow: hidden;
    padding: 0px;
}
body
{
    border: 0px;
    margin: 0px;
    overflow: hidden;
    padding: 0px;
}

Let’s take a look at the CSS. We use styling to position the DIV, as well as styling to ensure the object tag uses all of the available DIV. Finally we use some tricks to eliminate overflowing content and remove the horizontal scrollbar.

Oracle Policy Automation Embed Website in Interview Debugging

As mentioned earlier, this may be best tested in the Browser, not in the Debug Embedded Browser, so make sure you start with Ctrl+Debug.

The first screen will be straightforward:

Oracle Policy Automation Embed Website in Interview 1

The second screen will display and if your Internet connection is slow, you may have time to witness the two stages of display:

Stage 1 : Show the styled DIV that has been added to the Screen. Of course you don’t have to use this colour, I just wanted to use it for positioning and effect.

Oracle Policy Automation Embed Website in Interview DIV

Stage 2 : The embedded Website is displayed. The embedding is seamless (nice colour scheme!).

Oracle Policy Automation Embed Website in Interview End

  1. Notice that the attribute value has been passed to the OPA Hub Website and a search has been performed for you. The site is fully functional and can be accessed from the Interview Window.

Have a nice day! (The PDF is in the OPA Hub Shop).