If you ever had a requirement to constrain an assocoation applet, you might be familiar with one of the methods:
To be honest, I always felt guilty using above methods and kept looking for a more declarative way. And finally found it.
Let's say you need to constrain a [Contact Assoc Applet] with Opportunity's primary organisation => so you'll assoc only contacts which are from the same org as your opportunity.
First thing you'll need to do is to change an applet class to be CSSSWEFrameSIAAssocList.
Now create a couple of applet user properties:
User Property | Value | Description |
---|---|---|
BC Field Search LHS | [Primary Organization Id] = | Left (static) part of spec. A field mentioned here is from assoc applet's BC. |
Parent BC Constraint Field | Primary Organization Id | Right (dynamic) part of spec is a field name from your list applet's parent BC (Opportunity) |
Applet is ready to be compiled and tested!
As a result Siebel will construct a named search spec as shown in a log below:
... Named search [Associate Constraint Search]: [Primary Organization Id] ='2-9EZ5U1'
Afterword
As I already mentioned, these UserProps are part of a specific class, which means you can't use it together with other useful UserProprs from different classes (for example, Override Visibility)
Also keep in mind that you are now bond to parent BC field name. Association applet will fail, if used in the context, where parent BC doesn't have a referenced field.
What if you can run eScript code without even opening Siebel Tools. Right from the Siebel client.
Need to code a new service? Click your favourite bookmarklet button and prototype it immediately, no need of recompilations/restarts.
Need to hook into a current BO context and manipulate active BCs? Easy!
Before I start, I have to say this idea haven't visited my head first. If you need a full immersion you should ask my masterminds - Jason or Roy.
So, here is how you build a lightweight eScript interactive playground.
As you may have guessed, it is all around eval() function. First step is to make it invokable from the browser:
1. Create a Business Service, as simple as this one:
function Service_PreInvokeMethod (MethodName, Inputs, Outputs) {
if (MethodName == “EvalScript”){
try {
Outputs.SetProperty(“Result”, eval(Inputs.GetProperty(“Expr”)));
} catch(e) {
Outputs.SetProperty(“Result”, e.toString());
}
}
return (CancelOperation);
}
A little trick here is to create the BS as a client-side business service, so it wouldn't be a part of repository => neither part of regular migrations => no security bleach on production.
2. Publish the service, so it can be accessible from a browser:
You will need a dialog with input and output text areas and a button to run the BS. Here is how your JS will look like:
// dialog html
var s = '<div title="eScript">'
+ '<textarea id = "SiebelEvalScript" style="height:150px"></textarea>'
+ '<textarea id = "SiebelEvalScriptOut" rows="4" disabled></textarea>'
+ '<style>textarea{width:100%!Important}</style>'
+ '</div>';
// display dialog
$(s).dialog({
modal: true,
width: 1024,
buttons: [{text:'Run', click: Eval}]
});
// run Business Service
function Eval(){
var sRes = "";
var ps = SiebelApp.S_App.NewPropertySet();
ps.SetProperty("Expr", $('#SiebelEvalScript').val());
var outputSet = SiebelApp.S_App.GetService("FWK Runtime").InvokeMethod("EvalScript", ps);
if (outputSet.GetProperty("Status") == "Error"){
sRes = outputSet.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg");
}else{
sRes = outputSet.GetChildByType("ResultSet").GetProperty("Result");
}
$('#SiebelEvalScriptOut').text(sRes);
}
Try it in browser console or compile into a bookmarklet.
Don't have time building your own playground? Try mine, it is free and has some advanced features you might enjoy:
Front: Source code, Bookmarklet code, Bookmarklet
/*
@desc Framework allowing to run/evaluate eScript code
@author VB(xapuk.com)
@version 1.3 2018/12/05
@requires BS=FWK Runtime to be published
*/
if ("undefined" == typeof SiebelApp){
alert("It works only in Siebel OUI session!");
}else{
var editor; // AceJS editor object
var func = "SiebelEvalScript"; // function identifier
var snip; // an array of saved snippets
var last; // current snippet name
// dialog html
var s = '<div title="eScript">'
+ '<select id = "' + func + 'List" style="display:block"><option value="*">New...</option></select>'
+ '<textarea id = "' + func + '" placeholder="eSciript code..." style="height:150px"></textarea>'
+ '<label id = "' + func + '_lbl" for="' + func + '">Initialised</label>'
+ '<textarea id = "' + func + 'Out" rows="4" disabled></textarea>'
+ '<style>select,textarea{width:100%!Important}.ui-dialog-content{padding:0.5em 1em}</style>'
+ '</div>';
// hard-remove dialog object from DOM, just in case
$("#"+func + "List").parent().remove();
var d = $(s).dialog({
modal: true,
width: 1024,
open: function(){
$('#'+func).focus();
// load acejs plugin
if (typeof(ace) == "undefined"){
// injecting a script tag, also you can use require() function instead
var jsCode = document.createElement('script');
jsCode.setAttribute('src', "https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.2/ace.js");
jsCode.setAttribute('async', true);
jsCode.onload = attachACE;
document.body.appendChild(jsCode);
}else{
attachACE();
}
// List onchange
$("#"+func+"List").change(function(event) {
var n = $(this).val();
if (n != "*" && n > ""){
if (editor){
editor.setValue(snip[n]);
}else{
$("#"+func).text(snip[n]);
}
window.localStorage[func+"Last"] = n;
}
});
// key bindings
$("#"+func+"Out").parent().keydown(function(event) {
if (event.ctrlKey && event.keyCode === 13) { // ctrl + Enter
Eval();
return false;
}else if (event.ctrlKey && event.keyCode === 83) { // ctrl + S
Save();
return false;
}
});
Load(); // load presaved params
},
close: function(){
$(this).dialog('destroy').remove();
},
buttons: [
{
text:'Run (Ctrl+Enter)',
click: Eval
},
{
text:'Save (Ctrl + S)',
click: Save
},
{
text:'Remove',
click: Delete
},
{
text:'Close (Esc)',
click: function() {
$(this).dialog('close');
}
}
]
});
}
function Eval(){
var sExpr = GetCode();
var sRes = "";
var dTS = new Date();
var isChrome = !!window.chrome;
var isFirefox = typeof InstallTrigger !== 'undefined';
// execution timestamp
$('#'+func + "_lbl").text("Last executed at " + dTS.toISOString().replace("T", " ").replace("Z", " "));
Save(); // save snippets every time you run it
// invoke BS
var service = SiebelApp.S_App.GetService("FWK Runtime");
var ps = SiebelApp.S_App.NewPropertySet();
ps.SetProperty("Expr", sExpr);
var outputSet = service.InvokeMethod("EvalScript", ps);
if (outputSet.GetProperty("Status") == "Error"){
sRes = outputSet.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg");
}else{
sRes = outputSet.GetChildByType("ResultSet").GetProperty("Result");
}
$('#'+func + "Out").text(sRes);
// show results in browser console
if (console) {
var a = sRes.split(String.fromCharCode(13));
for(var i = 0; i < a.length; i++) {
// split into 3 parts for styling
var a2 = a[i].split('\t|\t');
var s1 = "", s2 = "", s3= "";
if (a2.length > 1){
if (a2.length > 2){
s1 = a2[0];
s2 = a2[1];
for(var j = 2; j < a2.length; j++) {
s3 += "\t" + a2[j];
}
} else {
s1 = a2[0];
s3 = a2[1];
}
} else {
s3 = a[i];
}
// collapse miltiline results
if (s3.indexOf("\n") > -1) {
if (isFirefox || isChrome ) {
console.groupCollapsed("%c" + s1 + " \t%c" + s2, "color:DarkCyan;", "color:Maroon;font-weight:bold");
} else {
console.groupCollapsed(s1 + " \t" + s2);
}
console.log(s3);
console.groupEnd();
} else {
if (isFirefox || isChrome ) {
console.log("%c" + s1 + " \t%c" + s2 + " \t%c" + s3, "color:DarkCyan;", "color:Maroon;font-weight:bold", "color:black;font-weight:normal");
} else {
console.log(s1 + " \t" + s2 + " \t" + s3);
}
}
}
}
}
// attach acejs plugin
function attachACE(){
editor = ace.edit(func);
editor.session.setMode("ace/mode/javascript");
$(".ace_editor").css("height","300");
}
// save button
function Save(){
var n = $('#' + func + "List").val();
if (n == "*" || n == null){ // new
n = prompt("Snippet name");
if(n){
if (n.match(/.{2,}/)){
snip[n] = GetCode(true);
window.localStorage[func] = JSON.stringify(snip);
$('#' + func + "List").append('<option value="' + n + '">' + n +'</option>');
$('#' + func + "List").val(n).change();
}else{
alert("Invalid snippet name!");
}
}
}else{ // existing
snip[n] = GetCode(true);
window.localStorage[func] = JSON.stringify(snip);
}
}
// Remove button
function Delete(){
var n = $('#' + func + "List").val();
if (confirm("Are you sure you want to delete a snippet: " + n)){
if (n && n != "*"){
delete snip[n]; // remove item
window.localStorage[func] = JSON.stringify(snip);
delete window.localStorage[func + "Last"];
Load(); // reload list
}
}
}
// loads preserved code snippets
function Load() {
var s = window.localStorage[func];
// remove all dropdown items
$("#" + func + "List option").remove();
//clear editor
if (editor){
editor.setValue("");
}else{
$("#"+func).text("");
}
// retrieve code snippets saved in local storage
var li = '';
if (s){
snip = JSON.parse(s);
for (k in snip){
li += '<option value="' + k + '">' + k + '</option>';
}
}else{
snip={};
}
$("#" + func + "List").append(li);
//last snippet
last = window.localStorage[func+"Last"];
if(last){
$('#' + func + "List").val(last).change();
}
}
// returns either selected peace of code or full value from text area or ACEJS plugin
function GetCode(bFull)
{
var sRes;
if (editor){
if (bFull || editor.getSelectedText() === ""){
sRes = editor.getValue();
}else{
sRes = editor.getSelectedText();
}
}else{
var textComponent = document.getElementById(func);
if (bFull){
sRes = $('#'+func).val();
}else if(textComponent.selectionStart !== undefined && textComponent.selectionStart != textComponent.selectionEnd){// Normal browsers
sRes = textComponent.value.substring(textComponent.selectionStart, textComponent.selectionEnd);
}else if(document.selection !== undefined){// IE
textComponent.focus();
var sel = document.selection.createRange();
sRes = sel.text;
}else{
sRes = $('#'+func).val();
}
}
return sRes;
}
javascript:void function(){function e(){var e=n(),t="",l=new Date,i=!!window.chrome,a="undefined"!=typeof InstallTrigger;$("#"+s+"_lbl").text("Last executed at "+l.toISOString().replace("T"," ").replace("Z"," ")),o();var r=SiebelApp.S_App.GetService("FWK Runtime"),c=SiebelApp.S_App.NewPropertySet();c.SetProperty("Expr",e);var d=r.InvokeMethod("EvalScript",c);if(t="Error"==d.GetProperty("Status")?d.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg"):d.GetChildByType("ResultSet").GetProperty("Result"),$("#"+s+"Out").text(t),console)for(var p=t.split(String.fromCharCode(13)),u=0;u<p.length;u++){var f=p[u].split(" | "),g="",v="",S="";if(f.length>1)if(f.length>2){g=f[0],v=f[1];for(var y=2;y<f.length;y++)S+=" "+f[y]}else g=f[0],S=f[1];else S=p[u];S.indexOf("\n")>-1?(a||i?console.groupCollapsed("%c"+g+" %c"+v,"color:DarkCyan;","color:Maroon;font-weight:bold"):console.groupCollapsed(g+" "+v),console.log(S),console.groupEnd()):a||i?console.log("%c"+g+" %c"+v+" %c"+S,"color:DarkCyan;","color:Maroon;font-weight:bold","color:black;font-weight:normal"):console.log(g+" "+v+" "+S)}}function t(){a=ace.edit(s),a.session.setMode("ace/mode/javascript"),$(".ace_editor").css("height","300")}function o(){var e=$("#"+s+"List").val();"*"==e||null==e?(e=prompt("Snippet name"),e&&(e.match(/.{2,}/)?(r[e]=n(!0),window.localStorage[s]=JSON.stringify(r),$("#"+s+"List").append('<option value="'+e+'">'+e+"</option>"),$("#"+s+"List").val(e).change()):alert("Invalid snippet name!"))):(r[e]=n(!0),window.localStorage[s]=JSON.stringify(r))}function l(){var e=$("#"+s+"List").val();confirm("Are you sure you want to delete a snippet: "+e)&&e&&"*"!=e&&(delete r[e],window.localStorage[s]=JSON.stringify(r),delete window.localStorage[s+"Last"],i())}function i(){var e=window.localStorage[s];$("#"+s+"List option").remove(),a?a.setValue(""):$("#"+s).text("");var t="";if(e){r=JSON.parse(e);for(k in r)t+='<option value="'+k+'">'+k+"</option>"}else r={};$("#"+s+"List").append(t),c=window.localStorage[s+"Last"],c&&$("#"+s+"List").val(c).change()}function n(e){var t;if(a)t=e||""===a.getSelectedText()?a.getValue():a.getSelectedText();else{var o=document.getElementById(s);if(e)t=$("#"+s).val();else if(void 0!==o.selectionStart&&o.selectionStart!=o.selectionEnd)t=o.value.substring(o.selectionStart,o.selectionEnd);else if(void 0!==document.selection){o.focus();var l=document.selection.createRange();t=l.text}else t=$("#"+s).val()}return t}if("undefined"==typeof SiebelApp)alert("It works only in Siebel OUI session!");else{var a,r,c,s="SiebelEvalScript",d='<div title="eScript"><select id = "'+s+'List" style="display:block"><option value="*">New...</option></select><textarea id = "'+s+'" placeholder="eSciript code..." style="height:150px"></textarea><label id = "'+s+'_lbl" for="'+s+'">Initialised</label><textarea id = "'+s+'Out" rows="4" disabled></textarea><style>select,textarea{width:100%!Important}.ui-dialog-content{padding:0.5em 1em}</style></div>';$("#"+s+"List").parent().remove();{$(d).dialog({modal:!0,width:1024,open:function(){if($("#"+s).focus(),"undefined"==typeof ace){var l=document.createElement("script");l.setAttribute("src","https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.2/ace.js"),l.setAttribute("async",!0),l.onload=t,document.body.appendChild(l)}else t();$("#"+s+"List").change(function(e){var t=$(this).val();"*"!=t&&t>""&&(a?a.setValue(r[t]):$("#"+s).text(r[t]),window.localStorage[s+"Last"]=t)}),$("#"+s+"Out").parent().keydown(function(t){return t.ctrlKey&&13===t.keyCode?(e(),!1):t.ctrlKey&&83===t.keyCode?(o(),!1):void 0}),i()},close:function(){$(this).dialog("destroy").remove()},buttons:[{text:"Run (Ctrl+Enter)",click:e},{text:"Save (Ctrl + S)",click:o},{text:"Remove",click:l},{text:"Close (Esc)",click:function(){$(this).dialog("close")}}]})}}}();
Back: Service, and don't forget about Application UserProp