This BPM on Ice.BO.ShellLayout.GetHomePageForUser (Post) injects your HTML directly as base64 encoded data and loads it as an iframe src into the second tile of a new home page tab group that is injected into whatever home page the user has set/configured. (so it will load no matter what the user’s got as a set up homepage)
This can also be saved into Db.ShellLayout so that it can load without needing the bpm, but i loaded it this way for easy testing, i just have to change the object in C# to adjust the home page.
This works successfully to load your designed html page into an iframe, but the javascript inside doesn’t seem to take effect on the parent homepage.
The javascript probably has to be tweaked to affect the parent page from here, or something or other. Or maybe browser security won’t let it because it’s loading from a [null] context vs. the url the rest of kinetic is loading from. I’ll play around more tomorrow.
//using Newtonsoft.Json;
//using Newtonsoft.Json.Linq;
var webPropsGroup = new JObject {
["hidden"] = false,
["x"] = 0,
["y"] = 0,
["width"] = 10,
["height"] = 6,
["kinetic"] = true,
["sequence"] = 0
};
var webPropsTile = new JObject
{
["kinetic"] = true,
["xx"] = 0,
["yy"] = 0,
["width"] = 2,
["height"] = 2
};
var newGroup = new HomeTileGroupRow {
GroupID = 1,
Title = "Epicor",
Sequence = 1,
IsFaveDefault = false,
Type = "L",
Retain = false,
SysRowID = Guid.NewGuid(),
RowMod = "A",
WebProperties = webPropsGroup.ToString()
};
var json = JsonConvert.SerializeObject(result.HomeTileGroup);
var arr = JArray.Parse(json);
var newJRow = new JObject {
["GroupID"] = newGroup.GroupID,
["Title"] = newGroup.Title,
["Sequence"] = newGroup.Sequence,
["IsFaveDefault"] = newGroup.IsFaveDefault,
["Type"] = newGroup.Type,
["Retain"] = newGroup.Retain,
["SysRowID"] = newGroup.SysRowID.ToString(),
["RowMod"] = newGroup.RowMod,
["WebProperties"] = newGroup.WebProperties
};
arr.Insert(0, newJRow);
result.HomeTileGroup.Clear();
foreach(var item in arr) {
result.HomeTileGroup.Add(JsonConvert.DeserializeObject<HomeTileGroupRow>(item.ToString()));
}
var devTile = new HomeTileRow {
TileID = 1001,
GroupID = newGroup.GroupID,
Sequence = 10,
Type = "K",
LinkType = "F",
Color = "FaveColor5",
DefaultWidth = 2,
DefaultHeight = 2,
MaxWidth = 2,
MaxHeight = 2,
ExpandedFlag = false,
Title = "Dev Tools",
Path = "UDDVTOOL",
DisplayType = "D",
DisplayPath = "",
RefreshInterval = 0,
Company = "",
Appserver = "",
Plant = "",
WebProperties = webPropsTile.ToString(),
OpenInNewTab = true,
ImageBlob = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="),
RowMod = "A"
};
var embedHTMLTile = new HomeTileRow {
TileID = 1002,
GroupID = newGroup.GroupID,
Type = "K",
Path = "data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PHNjcmlwdD5mdW5jdGlvbiB3YWl0Rm9yTWVudVRoZW5DbGljaygpeyBsZXQgdGltZXIgPSAwOyBjb25zdCBwb2xsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7IGxldCBtZW51RWxlbWVudCA9IHBhcmVudC5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdsaSNNZW51Jyk7IGlmIChtZW51RWxlbWVudCkgeyBjbGVhckludGVydmFsKHBvbGxJZCk7IHNldFRpbWVvdXQoKCkgPT4geyBpZihwYXJlbnQuZG9jdW1lbnQudGl0bGU9PSdIb21lJyl7IG1lbnVFbGVtZW50LmNsaWNrKCk7IGNvbnN0IGlzU21hcnRDbGllbnQgPSAocGFyZW50Lm91dGVySGVpZ2h0IC0gcGFyZW50LmlubmVySGVpZ2h0ID09IDApOyBpZiAoaXNTbWFydENsaWVudCkgeyBzZXRUaW1lb3V0KCgpID0+IHsgY29uc3QgdGh1bWJ0YWNrRWxlbWVudCA9IHBhcmVudC5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdpLmVwLXBpbm5lZC1hbGxvdycpOyBpZiAodGh1bWJ0YWNrRWxlbWVudCkgeyB0aHVtYnRhY2tFbGVtZW50LmNsaWNrKCk7IH0gfSwgNTAwKTsgfSB9IH0sIDUwMCk7IH0gZWxzZSB7IHRpbWVyICs9IDEwMDsgaWYgKHRpbWVyID4gMTAwMDApeyBjbGVhckludGVydmFsKHBvbGxJZCk7IH0gfSB9LCAxMDApOyB9IHdhaXRGb3JNZW51VGhlbkNsaWNrKCk7PC9zY3JpcHQ+PC9oZWFkPjxib2R5Pk1lbnUtQXV0by1PcGVuIFdpZGdldDwvYm9keT48L2h0bWw+",
LinkType = "U",
DisplayType = "D",
DisplayPath = "",
LineLinkType = "",
LinePath = "",
BaqId = "",
Color = "FaveColor5",
Title = "testingtitle",
DefaultWidth = 1,
DefaultHeight = 1,
MaxWidth = 1,
MaxHeight = 1,
ListImage = "",
FavoriteFolderSeq = 0,
ExpandedFlag = false,
BaqColumnList = "",
Sequence = 20,
RelatedMenuId = "",
RefreshInterval = 0,
Company = "",
Appserver = "",
BaqContextColumn = "",
Plant = "",
MetricAggregate = "",
MetricTextPrefix = "",
MetricTextSuffix = "",
MetricImage = "",
MetricTextFontSize = 0,
ImageRowID = Guid.Empty,
ImageBlob = null,
ImageFilename = "",
WebProperties = "{\"token\":false,\"context\":false,\"kinetic\":true,\"xx\":2,\"yy\":0,\"width\":2,\"height\":2}",
OpenInNewTab = false,
SysRowID = Guid.Empty,
RowMod = "A"
};
var tileJson = JsonConvert.SerializeObject(result.HomeTile);
var tileArr = JArray.Parse(tileJson);
var devJRow = JObject.FromObject(devTile);
var embedHTMLJRow = JObject.FromObject(embedHTMLTile);
tileArr.Insert(0, embedHTMLJRow);
tileArr.Insert(0, devJRow);
result.HomeTile.Clear();
foreach (var t in tileArr)
result.HomeTile.Add(JsonConvert.DeserializeObject<HomeTileRow>(t.ToString()));
In Dev Tools / Elements, I can see the iframe src rendering properly:
Ahh, I think it is browser security preventing it, i can see your function executing repeatedly on it’s timer, but not finding the menu:

Maybe we could inject a listener into the parent homepage that the child iframe can talk to. (but then I guess, if we can inject into parent homepage, we just put the script there instead
)… Hmmm…
Validated, if I launch chrome with web security disabled, it functions just fine.
& "C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:/ChromeDev"
Hmmm.. I’m thinking what if we upload the html somewhere sanctioned by Sandbox.IO and accessible via a direct url link.. like into the Company folder and then we craft a URL that is a REST or odata call to pull that file into the iframe… Ice.Lib.FileTransferSvc doesn’t have a GET version of DownloadFile tho.. … hmmm