When reloading state, ask for a re-render of each dashlet as we'll need their scripts to be re-executed (that also make the data refresh)

This commit is contained in:
Stephen Abello
2026-01-23 11:05:16 +01:00
parent 1bb7ddd488
commit ceda1d40f8
4 changed files with 57 additions and 39 deletions

View File

@@ -49,7 +49,7 @@ class IboGridSlot extends HTMLElement {
height: this.iHeight
};
const aDashletData = oDashlet ? oDashlet.Serialize(bIncludeHtml) : {};
const aDashletData = oDashlet ? oDashlet.Serialize() : {};
return {
...aSlotData,

View File

@@ -71,7 +71,8 @@ class IboGrid extends HTMLElement {
// Get the dashlet as an object
const oParser = new DOMParser();
const oDocument = oParser.parseFromString(sDashlet, 'text/html');
const oDashlet = oDocument.body.firstChild;
const oDashlet = oDocument.body.querySelector('ibo-dashlet');
const aScripts = oDocument.body.querySelectorAll('script');
const oSlot = IboGridSlot.MakeNew(oDashlet);
@@ -84,6 +85,20 @@ class IboGrid extends HTMLElement {
oSlot.scrollIntoView({ behavior: "smooth"});
aScripts.forEach( oScript => {
if (oScript) {
const oNewScriptElement = document.createElement('script');
// copy attributes
[...oScript.attributes].forEach(attr =>
oNewScriptElement.setAttribute(attr.name, attr.value)
);
oNewScriptElement.text = oScript.textContent;
oSlot.querySelector('ibo-dashlet').after(oNewScriptElement);
}
});
return oDashlet.sDashletId;
}
@@ -91,7 +106,7 @@ class IboGrid extends HTMLElement {
const oParser = new DOMParser();
const oDocument = oParser.parseFromString(sDashlet, 'text/html');
const oNewDashlet = oDocument.body.querySelector('ibo-dashlet');
const oNewScript = oDocument.body.querySelectorAll('script');
const aNewScripts = oDocument.body.querySelectorAll('script');
// Can't use oNewDashet.sDashletId as it's not in the DOM yet and connectedCallback hasn't been called yet
const oExistingDashlet = this.GetDashletElement(oNewDashlet.getAttribute('data-dashlet-id') );
@@ -119,7 +134,7 @@ class IboGrid extends HTMLElement {
}
// Append scripts to body so they are executed
oNewScript.forEach( oScript => {
aNewScripts.forEach( oScript => {
if (oScript) {
const oNewScriptElement = document.createElement('script');
@@ -129,7 +144,7 @@ class IboGrid extends HTMLElement {
);
oNewScriptElement.text = oScript.textContent;
document.body.appendChild(oNewScriptElement);
oSlotForExistingDashlet.querySelector('ibo-dashlet').after(oNewScriptElement);
}
});
}
@@ -166,11 +181,11 @@ class IboGrid extends HTMLElement {
this.oGrid.removeAll();
}
Serialize(bIncludeHtml = false) {
Serialize() {
const aSlots = this.getSlots();
return aSlots.reduce((aAccumulator, oSlot) => {
aAccumulator[oSlot.oDashlet.sDashletId] = oSlot.Serialize(bIncludeHtml);
aAccumulator[oSlot.oDashlet.sDashletId] = oSlot.Serialize();
return aAccumulator;
}, {});
}

View File

@@ -86,7 +86,7 @@ class IboDashboard extends HTMLElement {
if(this.bEditMode){
// TODO 3.3 If we are in default dashboard display, change to custom to allow editing
// TODO 3.3 Get the custom dashboard and load it, show a tooltip on the dashboard toggler to explain that we switched to custom mode
this.aLastSavedState = this.Serialize(true);
this.aLastSavedState = this.Serialize();
this.setAttribute("data-edit-mode", "edit");
}
else{
@@ -95,14 +95,9 @@ class IboDashboard extends HTMLElement {
}
AddNewDashlet(sDashletClass, sDashletValues, aDashletOptions = {}) {
let sNewDashletUrl = GetAbsoluteUrlAppRoot() + '/pages/UI.php?route=dashboard.get_dashlet&dashlet_class='+encodeURIComponent(sDashletClass);
let oGetDashletPromise = this.GetDashlet(sDashletClass, '', sDashletValues);
if(sDashletValues.length > 0) {
sNewDashletUrl += '&values=' + encodeURIComponent(sDashletValues);
}
fetch(sNewDashletUrl)
.then(async data => {
oGetDashletPromise.then(async data => {
const sDashletId = this.oGrid.AddDashlet(await data.text(), aDashletOptions);
@@ -112,16 +107,24 @@ class IboDashboard extends HTMLElement {
}
RefreshDashlet(oDashlet) {
let sGetDashletUrl = GetAbsoluteUrlAppRoot() + '/pages/UI.php?route=dashboard.get_dashlet&dashlet_class=' + encodeURIComponent(oDashlet.sType)
+'&dashlet_id=' + encodeURIComponent(oDashlet.sDashletId);
GetDashlet(sDashletClass, sDashletId = '', sDashletValues = '') {
let sGetDashletUrl = GetAbsoluteUrlAppRoot() + '/pages/UI.php?route=dashboard.get_dashlet&dashlet_class='+encodeURIComponent(sDashletClass);
if(oDashlet.formData.length > 0) {
sGetDashletUrl += '&values=' + encodeURIComponent(oDashlet.formData);
if(sDashletId.length > 0) {
sGetDashletUrl += '&dashlet_id=' + encodeURIComponent(sDashletId);
}
return fetch(sGetDashletUrl)
.then(async data => {
if(sDashletValues.length > 0) {
sGetDashletUrl += '&values=' + encodeURIComponent(sDashletValues);
}
return fetch(sGetDashletUrl);
}
RefreshDashlet(oDashlet) {
let oGetDashletPromise = this.GetDashlet(oDashlet.sType, oDashlet.sDashletId, oDashlet.formData);
return oGetDashletPromise.then(async data => {
this.oGrid.RefreshDashlet(await data.text());
});
@@ -299,11 +302,11 @@ class IboDashboard extends HTMLElement {
)
}
Serialize(bIncludeHtml = false) {
Serialize() {
const sDashboardTitle = this.querySelector('.ibo-dashboard--form--inputs input[name="dashboard_title"]').value;
const sDashboardRefreshRate = this.querySelector('.ibo-dashboard--form--inputs select[name="refresh_interval"]').value;
const aSerializedGrid = this.oGrid.Serialize(bIncludeHtml);
const aSerializedGrid = this.oGrid.Serialize();
return {
schema_version: this.schemaVersion,
id: this.sId,
@@ -324,7 +327,7 @@ class IboDashboard extends HTMLElement {
const res = await data.json();
if(res.status === 'ok') {
CombodoToast.OpenToast(res.message, 'success');
this.aLastSavedState = this.Serialize(true);
this.aLastSavedState = this.Serialize();
this.SetEditMode(false);
} else {
CombodoToast.OpenToast(res.message, 'error');
@@ -370,16 +373,20 @@ class IboDashboard extends HTMLElement {
const iHeight = aDashletData.height;
const aDashlet = aDashletData.dashlet;
// We store the dashlet component in the HTML, not only the rendered dashlet
const sDashetHtml = aDashlet.html;
// We need to fetch dashlet HTML from server as scripts need to be executed again
let oGetDashletPromise = this.GetDashlet(aDashlet.type, aDashlet.id, JSON.stringify(aDashlet.properties));
// Add dashlet to grid with its position and size
this.oGrid.AddDashlet(sDashetHtml, {
x: iPosX,
y: iPosY,
w: iWidth,
h: iHeight,
autoPosition: false
oGetDashletPromise.then(async data => {
let sDashletHtml = await data.text();
// Add dashlet to grid with its position and size
this.oGrid.AddDashlet(sDashletHtml, {
x: iPosX,
y: iPosY,
w: iWidth,
h: iHeight,
autoPosition: false
});
});
}

View File

@@ -49,7 +49,7 @@ class IboDashlet extends HTMLElement {
return oDashlet;
}
Serialize(bIncludeHtml = false) {
Serialize() {
// TODO 3.3 Should we use getters ?
let aDashletData = {
id: this.sDashletId,
@@ -57,10 +57,6 @@ class IboDashlet extends HTMLElement {
properties: JSON.parse(this.formData),
};
if(bIncludeHtml) {
aDashletData.html = this.outerHTML;
}
return aDashletData;
}
}