Discussion
Pegasystems Inc.
US
Last activity: 25 Oct 2022 18:46 EDT
How to generate a toast when processing assignment in Theme Cosmos
The Cosmos design system has a toast component (see https://design.pega.com/design/toast/) that is used to display short messages exclusively to confirm a completed user action (such as a form submission). Toasts inform users that an action happened if users cannot see the action on screen.
This is a component that is not completely available in Theme-Cosmos and is only available in the Cosmos React implementation. In Theme-Cosmos, a toast is displayed only when creating a new case and if the newly created case is not immediately opened after clicking on the create button. This behavior can be configured in the Cosmos UI setting for each case type
Unfortunately the toast used in the create case is very specific to the Create modal dialog and is leveraging the confirm screen screen when completing a case. As such it is not reusable in other part of the flow.
In this post, I will explain how to implement such functionality. The changes were tested in Pega 8.6 using Theme-Cosmos 3.0, but should also work on 8.4 or 8.5 using older version of the Theme-Cosmos.
in the attached RAP, you will find a ruleset with 2 rules: a CSS file and a JS file
1/ Add the CSS file to your application skin
While you can add the css to your portal harness, it is always best practice to include it directly into your application skin as an additional stylesheet. This will allow you to use mixin variables directly into the CSS file so that your toast background and color can be changed by editing a mixin into your skin.
The CSS snippet is very simple and allows to dynamically insert the toast at the bottom of the screen. The settings that you might want to tweak are highlighted in red below (width, height, background and color). This code could be improved by using mixin variables instead of the hardcoded background color.
2/ Add the JS file to your portal harness
Open your portal harness, and add the js file under the 'script and styles' tab.
The JS file contains one public method to show the toast. You can use a runscript action in a button to show the toast anywhere in the UI using the function pega.utility.toast.show. For example
pega.utility.toast.show("this is my toast message");
The JS module will automatically handled the display of the toast when processing assignment. Editing the pyActionButton to add the runscript after the finishAssignment action will not work because the finishAssignment action can failed due to validation and there is no easy way to detect that an error was reported. In order to implement this functionality, the JS module listed to the events generated for the primary ajax container to determine if the flow has been processed.
The toasts can stack up and will shift automatically if the show method is called multiple times. The toast will also auto dismiss after 5 seconds or can be close using the close button.
Here is the snippet of Javascript
pega.namespace("pega.utility");
if (!pega.utility.toast) {
pega.utility.toast = (function() {
var AUTO_DISMISS_TIME_MS = 5000;
var _toasts = [];
var _harnessID = '';
var _toastcontainer;
/* Initialize the context, event listeners */
var _init = function() {
_toastcontainer = document.createElement("div");
_toastcontainer.className = "toast-container";
_toastcontainer.addEventListener("click", function(event) {
var el = event.target.closest(".toast-instance");
_close(el);
event.preventDefault();
});
document.body.appendChild(_toastcontainer);
pega.ui.EventsEmitter.subscribe("postACRender", function() {
var acName = pega.ctx.acName;
if (acName === 'acprimary' && _harnessID && pega.ctx.strDisplayHarnessParms !==
_harnessID) {
_show("Successfully completed!");
_harnessID = pega.ctx.strDisplayHarnessParms;
}
}, null, null, null);
pega.ui.EventsEmitter.subscribe("onHarnessUnload", function() {
var acName = pega.ctx.acName;
if (acName === 'acprimary') {
_harnessID = pega.ctx.strDisplayHarnessParms;
}
}, null, null, null);
}
/* render all the toasts */
var _render = function() {
for (var i = 0; i < _toasts.length; i++) {
_toasts[i].style = "transform: translateY(-" + 48 * (_toasts.length - i) + "px)";
}
}
/* close a toast */
var _close = function(el) {
if (!el || !el.classList) return;
el.classList.add("hide");
setTimeout(function() {
for (var j = 0; j < _toasts.length; j++) {
if (_toasts[j] === el) {
_toasts.splice(j, 1);
if (el) _toastcontainer.removeChild(el);
_render();
return;
}
}
}, 400);
};
/* show a toast */
var _show = function(msg) {
var mytoast = document.createElement("div");
mytoast.className = "toast-instance";
mytoast.innerHTML = "<span>" + msg +
"</span><button class='pzhc pzbutton Icon' title='close toast'><i class='pi pi-times pi-light'/></button></span>";
_toastcontainer.appendChild(mytoast);
_toasts.push(mytoast);
setTimeout(function() {
_render();
setTimeout(function() {
_close(mytoast)
}, AUTO_DISMISS_TIME_MS);
}, 10);
};
return {
show: function(msg) {
_show(msg);
},
init: function() {
_init();
}
}
})();
pega.utility.toast.init();
}
Here is a complete video and demonstration of the functionality.