Skip navigation

I assert that OPA content (excluding the input controls) frequently changes independently of the rules. 

 

For all OPA project architects, please bear with me on this long blog post.  Please just follow along for a bit.  It will be worth it if you take the time.

 

Let's look realistically at an example project included with OPA: the example Warranty project.

 

Realistically, the example Warranty project screens would need to be enhanced with much more information content prior to production.  Examine all the Warranty project screens to see what I mean:

 

 

My point in going through all the above screens is that in many (most?) real-world OPA applications, questions and answers (input controls) are accompanied with content. If the application above were to be published and maintained, the project team would need to anticipate frequent changes to the content independent of the rules.

 

Consider the following guidance:

Intent

Separate the architectural concerns of policy and content, putting policy management in OPA and content management in a CMS.  Policy is realized in rules and attributes collected with input controls.  Content is realized in html paragraphs, images, videos, documents and such. 

Problem

Content is often changed separately from rules, and content may contain separate life-cycle from rules. If content changes require new publishing of OPA policy rulesets, then that introduces additional life-cycle management issues.  Further, content addition directly inside of interviews tends to "clutter" interview screens. Content placed directly in interview screens is not easily shared, managed, and searched outside of the interview screens.

Discussion

An example follows.

 

The problem is most often seen when important notes, textual descriptions, and graphical media types are coded directly into OPA interview screens.  There are even interviews where the interview goal is to direct the interviewee through content.   The content itself frequently changes, but the rules to get to the content do not change. 

 

By using a CMS and having the CMS content show up in-line in the interview, the content can follow a different lifecycle than the rules.  When a CMS is used, the only requirements of the OPA interview screens are the interview control settings to display the content.  Generally, an OPA control that retrieves CMS content via a REST API is utilized.

 

The interview control to retrieve CMS content is written once, and used everywhere in the interview that content is needed.  The interview control can be displayed or not displayed based on OPA visibility rules.

 

As an added benefit, any content media types available in the CMS becomes available in OPA. Additional OPA controls do not need to be written for OPA to handle video or other media types.

 

Whats more?  The content can be formatted in a WYSIWYG editor in the CMS.  That means no more need to put html into labels...

 

Structure

In demonstrations, we tackled CMS integration by having an OPA label extension that displays content retrieved from a CMS REST API.  The interview control properties are set to either search, filter, or directly access content from the CMS.

 

The effect is that in the Interview, labels are placeholders for content and take up very little interview design real-estate.  That allows the interview focus to be on the various questions (inputs) and on the flow in general.  This has been seen to greatly simplify OPA interview screen development where a lot of varying content is involved.

 

Example

I put up a WordPress site (modern WordPress is a CMS for those architects living under a log) with information regarding Warranty.  This information can be changed by the business on the WordPress site with a WYSIWYG editor independently of OPA.  Changes appear real-time in OPA.

 

For OPA, I added a control extension that uses the WordPress API to retrieve content.  Content can be directly retrieved, retrieved via search, or retrieved via filters (keywords).

 

In OPA, the new interview Welcome screen looks as follows (with label properties used for each item of WordPress content):

 

This produces the following interview screen after publishing on the web:

Notice that the red alert, the image, and everything retrieved from the CMS is independent of the OPA rules and OPA interview screen development.  The business has freedom to change the content separately from the rules and input controls.

 

Also notice that the actual OPA interview screen is nice, condensed, and easily read for interview flow.

 

See the huge difference a quick CMS integration provided, compared to the original OPA interview screen shown again here:

This post is short.

 

Trying to be helpful, based on something I saw today I would like to point out that containers can be put to an "extra" use in OPA that is only obvious after it is explained. 

 

We all know containers provide "layout" for vertical and horizontal orientation. See the following: Oracle Policy Automation Documentation Library

 

Did you realize?  Containers provide AND and OR visibility logic to allow multiple "show-if" conditions to apply...

 

If you have 2 attributes (the attribute a, the attribute b) and you only want to display controls depending on values from both, you don't need to write a combining rule like the following example:

Containers within containers are AND logic if each container has "show if" or "hide if" for a different attribute.

 

Containers beside containers are OR logic if each container has "show if" or "hide if" for a different attribute.

That technique can be combined for more complex visibility logic, and I would note that this generally also helps organize similar content together.  All content dependent on the first and the second attribute now have reason to be co-located in the interview.

 

There is no need to create yet another top level attribute with an AND or OR logic just for visibility.  Those things clutter up your data model, in any case.

 

Less is more.  Hope this helps!

Paul Fowler

OPA Popups / Tooltips...

Posted by Paul Fowler Oct 28, 2018

Again, see my disclaimers in the last post.

 

I want to share something from a personal project of mine.  I have a similar need for this type of functionality at work, so I had reason to prototype with a project at home.  It takes a while to figure these tricks out, and I wish someone had posted this OPA code on the Internet.

 

Background: I play D&D with my family, and I have a need to convert D&D 4 encounters to D&D 5e encounters for a campaign that our family has been playing since 2007...

 

Monster/encounter conversion may seem simple, but it isn't simple because D&D 5e comes with its own set of rules for monsters and encounters.  Some of the 5e rules are very involved and thus are not automated anywhere I can find for free on the Internet.  This is the reason manual conversions are so dang difficult.  (Really, I automated about 15 pages of 5e rules.  5e, btw, is considered simpler that 4...)

 

So, I wrote my own encounter ruleset for my family campaign, although I won't share it for fear of legal issues with Wizards of the Coast.  This project is just for our family use anyway...

 

BUT, one challenge that I had was reminding myself all the implications of setting various attributes such as "Hit Die".  I didn't want to clutter up my interview screen with d&d notes...  What to do?

 

Popups:

 

I succeeded with popups in several ways, but I will show a simple method that allows the content of the popup to include attribute values...

 

First, the top of the interview screen is shown here.  Everything in blue has a popup that reminds me of what is possible and impacted per the 5e rules.  Further, the popups have OPA attributes embedded in them.

 

Now a demonstration screenshot of one of the Popups.  (Btw, this popup uses rules to compute the proper hit die per 5e rules when given creature size, constitution, and hp.  The "8d10 + 24" was created with OPA rules and is in an attribute.)

Kind of cool???  Click the blue text and get a popup!  Click the popup and it goes away.

 

In my development tab, it looks as follows:

Notice how I use properties on a label.  Also, note the label/popup has an attribute in it that can change depending on fields in the interview.  That means the text in the popup has to be dynamic... 

 

The javascript:

// Lets make a popup function... Here are the necessary properties:

 

//

// type : Popup

// title : <<Text such as "click me...">>

// id : <<an id for this popup>>

OraclePolicyAutomation.AddExtension({

   customLabel: function(control, interview) {

     if (control.getProperty("type") == "Popup" ) {

     var x;

     var t;

       return {

         mount : function(el){

           x = document.createElement("DIV");

           x.className = "popup";

           x.onclick = function() {

             var popup = document.getElementById(control.getProperty("id"));

             popup.classList.toggle("show"); 

           };

           x.innerHTML = control.getProperty("title");


           t = document.createElement("SPAN");

           t.className = "popuptext";

           t.id = control.getProperty("id");

           t.innerHTML = control.getCaption();


           x.appendChild(t);

           el.appendChild(x);

           },

         update : function(el){

           t.innerHTML = control.getCaption();

          }

        }

     }

  }

});

 

The CSS:

/* Popup container */

 

.popup {

   position: relative;

   display: inline-block;

   margin-left: 10px;

   margin-right: 10px;

   color: blue;

   cursor: pointer;

}


/* The actual popup (appears on top) */

.popup .popuptext {

   visibility: hidden;

   width: 600px;

   background-color: #555;

   color: #fff;

   text-align: left;

   border-radius: 6px;

   padding: 8px 0;

   position: absolute;

   z-index: 1;

   bottom: 125%;

   left: 50%;

   margin-left: -80px;

}


/* Popup arrow */

.popup .popuptext::after {

   content: "";

   position: absolute;

   top: 100%;

   left: 10%;

   margin-left: -5px;

   border-width: 5px;

   border-style: solid;

   border-color: #555 transparent transparent transparent;

}


/* Toggle this class when clicking on the popup container (hide and show the popup) */

.popup .show {

   visibility: visible;

   -webkit-animation: fadeIn 1s;

   animation: fadeIn 1s

}


/* Add animation (fade in the popup) */

@-webkit-keyframes fadeIn {

  from {opacity: 0;}

  to {opacity: 1;}

}


@keyframes fadeIn {

  from {opacity: 0;}

  to {opacity:1 ;}

}

 

Done.

 

PS:

 

Finally, I couldn't resist but use BI Publisher...  (Notice the Hit Die from above populated next to the Hit Points...)  I haven't had time to write rules for special qualities or actions, so ignore those areas.

 

For anyone who wonders, all the coding for D&D 5e creature rules could be done in only two weekends. Try doing that with just Excel...

 

I hope you can make use of this how-to code for popups/tooltips in OPA.   Let me know in comments if you take any of this code and modify it for your own projects, please.

Disclaimers and Background

Yes, there are several examples of OPA controls in javascript this post.  But, my pure "dev days" have been replaced by policy discussions.

 

Disclaimer #1: Forgive my javascript coding if it isn't up to par.

Disclaimer #2: I expect to upgrade this blog post content in the future.

Disclaimer #3: As always, I am not an Oracle employee, so use advice in this blog at your own risk.

 

As an architect, I am well aware that for the end user, the interface is the system.

 

To have a good interface, you must control styling and control the controls themselves.  However, OPA is about policy, not styling.  Lucky for us, OPA interviews are so dang easy to create!  For a "human interface" channel, OPA interview screens are extremely quick and good for the average person.

 

However, I have seen OPA interviews moved to PHP (instead of running in OPA) just due to styling.  Really I have, and I am not just saying that.

 

I have noticed that what every project asks on day 1 is "How do I put our organization's custom CSS for those menus and labels?"

 

Historically, what hasn't been great for OPA presentation UX is this following process:

 

In the old days, OPA modelers presented some finished OPA interview screens in a web browser.  Then the presentation designers ran the interview, parsed the HTML using browser developer tools and created the following (not-opa-recommended) types of jQuery:

 

$(document).on("click",function(event){

 

    if(!($(event.target).is("div.arrow_box") || $(event.target).is(".list-input")|| $(event.target).is(".ui-button-icon-primary") || $(event.target).is(".owd-input")))

        $('.arrow_box').addClass( "my-control-hidden" ); });

 

After that, the reverse engineered CSS was applied.  OPA would be upgraded a few years or months later, and styling things would break.

 

So, what is the OPA recommended UX styling (as of 2018) and how do we give designers more control?  How do designers learn to design to it???

 

On of my proposed solutions: Give your presentation team an OPA style playground project at the beginning of development.

 

May I suggest starting out with a playground OPA project for testing UI controls and styling?  I attached an example style playground.  Download the example and play with it, then hopefully your presentation team can avoid the whole "let's use PHP." 

 

Here are the steps I followed to create my presentation style playground project.

 

Step 1:  Read (and share) the documentation

Bookmark the following after reading them and share them for reference:

 

1) the Web Interview Developement Documentation for CSS/Javascript integration: Oracle Policy Automation Documentation Library

2) the Design Interviews Documentation for the in-program styling: Oracle Policy Automation Documentation Library

 

Note, I am on 18c.  In my experience, it isn't enough to just point designers at documentation, they need to be shown OPA.  Sit down with them for a few hours.

 

Step 2: Add the "custom files" directory to the project

Let OPA know you are going to use custom files.  Go to Interview->styles and click the "Custom Files" button.

 

Agree to the warning...

The directory will appear like magic.

 

Step 3: add jQuery, and other .js script libraries etc...

(Be aware, there are limitations.  Don't expect a full framework to be able to be included.)

jQuery is fine. I like to put my own jQuery, popper, and tooltip .js files into the project, although I think OPA already comes with some of this. 

 

 

Step 4: Get the organization's color palette from your design team and apply it to the "styles"

If your design team is not picky, and you are not a design guy, go to a site like Color Safe - accessible web color combinations or like https://flatuicolors.com/ and pick colors that look good together.  Make a "best guess" and give yourself a basic screen.  Really, I just changed the navigation bar and called it a day.

 

Note: picking colors that are WCAG compliant is really frustrating, but think of how frustrating it is to have trouble seeing...  Keep at it and never let the colors be anything but WCAG compliant. Hopefully you can get a palette from your design team that already covers WCAG.

 

Step 5: Figure out a "strategy" to style individual OPA controls, add your own .js and ask presentation guys for a .css file.

 

Strategy??? One possible "strategy" is to use control "properties" to identify a className for any "special control."  See Oracle Policy Automation Documentation Library Once a className is identified, the presentation guru's have a field day with CSS!

 

The presentation team and the policy team agree on properties that the controls should have for certain behaviors.  For example, here are custom properties on a label that gives a className of interview if my javascript is included.

 

Here is an example javascript to add classNames to my controls for CSS usage:  Note that I use a broad brush and make it possible to add a class to basically any control.  I do wonder if there is a more concise way to write this in javascript, but this works.

 

Eventually the javascript and CSS files should be turned over to the proper teams after they understand what is happening.  Policy folk shouldn't worry about javascript / CSS in my opinion.

 

//

// First, I make it possible to use CSS styling on any basic type of control

// Just add 2 properties to the control in the OPA interview:

// type : CSS

// className : <<class name to use in the CSS>>

//

OraclePolicyAutomation.AddExtension({

   style: {

        question: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

         },

       label: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        textInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        textAreaInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        calendarInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

             }

        },

        dropDownInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        filterDropDownInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        listInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        radioInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        checkboxInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        captchaInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

        },

        signatureInput: function(control, interview){

             if (control.getProperty("type") == "CSS" ) {

                  return { className: control.getProperty("className") }

            }

       }

  }

});

 

 

Step 6: Add any known necessary custom controls to a project.

I "cheat".  I add ability to turn a label into an html object and vice-versa early in my projects, even if it doesn't get used.  That provides flexibility.  Oracle, please don't crucify me...  As such, I can display videos inline, pdf files, get around the html restrictions, etc...

 

After our designers / developers get a look at my code, they can then modify it accordingly.

 

These are all examples.  I will let you guys mull over the examples and change them as you see fit.

 

My first custom control example is a label that when clicked can hide other labels of a specific class on the interview screen.  Why not use OPA hide/show functionality?  You could use OPA and I recommend OPA logic as a default.  In this case, we have screen "instruction text" that really is not part of an interview but is presented in one or more labels.  The help text is not used for any other interview channel and the help text contains html formatting, etc.  In other words, the help text is not part of the interview proper and we just want to be able to show/hide labels with the click of a label for instructional purposes on the screen.  tooltip.js is also good for this.

 

//

 

// Second, I need some way to show/hide sections...

// Just add 3 properties to a label in the OPA interview:

// type : Reveal

// target : <<class name of whatever we want to show/hide>>

// className : <<class name to use in the CSS>>

//

OraclePolicyAutomation.AddExtension({

   customLabel: function(control, interview) {

     if (control.getProperty("type") == "Reveal" ) {

       return {

         mount : function(el){

           var x = document.createElement("H2");

           var t = document.createTextNode(control.getCaption());

           x.className = control.getProperty("className");

           x.onclick = function() {

             $( "." + control.getProperty("target") ).toggle("slow"); 

           };

           x.appendChild(t);

           $(function(){

             el.appendChild(x);

             $("." + control.getProperty("className")).parent().parent().next('.opa-container-vertical').addClass(control.getProperty("target")); 

           });

         }

       }

     }

  }

});


//

// Third, I need some way to show pdfs, word docs and video on screen...

// Just add 4-5 properties to a label in the OPA interview:

// type : Object

// data : <<url of the media>>

// className : <<class name to use in the CSS>>

// localResource : true | false

// mediaType : <<IANA Media Type>>

//

OraclePolicyAutomation.AddExtension({

   customLabel: function(control, interview) {

     if (control.getProperty("type") == "Object" ) {

       return {

         mount : function(el){

           var x = document.createElement("OBJECT");

           var tx = document.createTextNode("alt : ");

           var a = document.createElement("A");

           var ta = document.createTextNode(control.getCaption());

           x.className = control.getProperty("className");

           if (control.getProperty("localResource") == "true") {

             x.data = "${resources-root}" + control.getProperty("data");

           } else {

             x.data = control.getProperty("data");

           };

           a.href = control.getProperty("data");

           if (control.getProperty("mediaType")) {

             x.type = control.getProperty("mediaType")

           };

           a.appendChild(ta);

           x.appendChild(a);

           x.appendChild(tx);

           el.appendChild(x);

         }

       }

     }

  }

});


//

// Fourth, I need some way to manage images, funny enough...

// Just add 3-5 properties to a label in the OPA interview: (height and width both optional)

// type : imgCSS

// src : <<the source link>>

// localResource : true | false

// alt : <<alt text for image>>

// className : <<class name to use in the CSS>>

// width : <<optional pixels>>

// height : <<optional pixels>>

//

OraclePolicyAutomation.AddExtension({

   customLabel: function(control, interview) {

     if (control.getProperty("type") == "imgCSS" ) {

       return {

         mount : function(el){

           var x = document.createElement("IMG");

           x.className = control.getProperty("className");

           if (control.getProperty("width")) {

             x.width = control.getProperty("width");

           };

           if (control.getProperty("height")) {

             x.height = control.getProperty("height");

           };

           x.alt = control.getProperty("alt");

           if (control.getProperty("localResource") == "true") {

             x.src = "${resources-root}" + control.getProperty("src");

           } else {

             x.src = control.getProperty("src");

          }

         el.appendChild(x);

         }

       }

     }

  }

});


//

// Fifth, I need some way to show html that has been embedded inside of an OPA attribute...

// Oracle will not like this.  It gets around their general html restrictions...

// Just add 1-2 properties to a label in the OPA interview:

// type : Attribute

// className : <<optional class name to use in the CSS>>

//

OraclePolicyAutomation.AddExtension({

   customLabel: function(control, interview) {

     if (control.getProperty("type") == "Attribute" ) {

       return {

         mount : function(el){

           var x = document.createElement("SPAN");

           let fragmentFromString = function (strHTML) {

             return document.createRange().createContextualFragment(strHTML);

           }

           let s = fragmentFromString(htmlDecode(control.getCaption()));

           if (control.getProperty("className")) {

             x.className = control.getProperty("className");

           }

           x.appendChild(s)

           el.appendChild(x);

         }

       }

     }

  }

});


// Helper functions to decode and encode html as provided by OPA

//

function htmlDecode(value) {

   return $("<textarea/>").html(value).text();

}

function htmlEncode(value) {

   return $('<textarea/>').text(value).html();

}

 

 

Step 7: Add every control / option to a project and let the designers mull it out and test the results.  The designers are involved from Day 1 on any project I work with.

 

This may confuse some of you, but the idea is actually simple.  I put every combination of control onto interview screens, so we could see how the styling "worked".

The menus can be examined, the entities, relating entities, every type of input and output is on interview screens for UX examination and alteration.

 

The net result is that someone should go through every screen of the playground interview and approve of the styling.  If that is done, 90% of a production project based on (or including) this project for styling should style correctly.

 

Final, after the styling is done, you can include this project as a base project for others.  You can delete all the screens, rules, and attributes, and keep the rest.  Feel free to ask questions or give suggestions in comments.

 

Again, I may update this blog post with a newer / better version in the future.

 

Enough Talk... sample style playground project is included.