diff --git a/js/layouts/dashboard/dashboard-grid-slot.js b/js/layouts/dashboard/dashboard-grid-slot.js index 0dbf0fd26b..6382b7a96b 100644 --- a/js/layouts/dashboard/dashboard-grid-slot.js +++ b/js/layouts/dashboard/dashboard-grid-slot.js @@ -49,7 +49,7 @@ class IboGridSlot extends HTMLElement { height: this.iHeight }; - const aDashletData = oDashlet ? oDashlet.Serialize(bIncludeHtml) : {}; + const aDashletData = oDashlet ? oDashlet.Serialize() : {}; return { ...aSlotData, diff --git a/js/layouts/dashboard/dashboard-grid.js b/js/layouts/dashboard/dashboard-grid.js index 6ce610a73f..05af7741ec 100644 --- a/js/layouts/dashboard/dashboard-grid.js +++ b/js/layouts/dashboard/dashboard-grid.js @@ -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; }, {}); } diff --git a/js/layouts/dashboard/dashboard.js b/js/layouts/dashboard/dashboard.js index 42f05ee455..fcd5a5024d 100644 --- a/js/layouts/dashboard/dashboard.js +++ b/js/layouts/dashboard/dashboard.js @@ -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 + }); }); } diff --git a/js/layouts/dashboard/dashlet.js b/js/layouts/dashboard/dashlet.js index d2412257f9..e6f0788e75 100644 --- a/js/layouts/dashboard/dashlet.js +++ b/js/layouts/dashboard/dashlet.js @@ -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; } }