diff --git a/tools/rum/charts/skyline.js b/tools/rum/charts/skyline.js index c0b903db..ef28d780 100644 --- a/tools/rum/charts/skyline.js +++ b/tools/rum/charts/skyline.js @@ -628,5 +628,15 @@ export default class SkylineChart extends AbstractChart { this.lcpAlreadyLabeled = false; this.chart.update(); + + this.loaded(); + } + + loading() { + this.elems.loading.ariaHidden = 'false'; + } + + loaded() { + this.elems.loading.ariaHidden = 'true'; } } diff --git a/tools/rum/elements/facetsidebar.js b/tools/rum/elements/facetsidebar.js index 329ba677..2c09fa15 100644 --- a/tools/rum/elements/facetsidebar.js +++ b/tools/rum/elements/facetsidebar.js @@ -75,4 +75,30 @@ export default class FacetSidebar extends HTMLElement { if (facetEl) this.elems.facetsElement.append(facetEl); }); } + + enableFacets() { + const existingFacetElements = Array.from(this.elems.facetsElement.children); + existingFacetElements.forEach((facet) => { + if (facet.enable) { + facet.enable(); + } else { + facet.querySelectorAll('input').forEach((input) => { + input.disabled = false; + }); + } + }); + } + + disableFacets() { + const existingFacetElements = Array.from(this.elems.facetsElement.children); + existingFacetElements.forEach((facet) => { + if (facet.disable) { + facet.disable(); + } else { + facet.querySelectorAll('input').forEach((input) => { + input.disabled = true; + }); + } + }); + } } diff --git a/tools/rum/explorer.html b/tools/rum/explorer.html index 477b257b..80b330a1 100644 --- a/tools/rum/explorer.html +++ b/tools/rum/explorer.html @@ -97,6 +97,9 @@

TTFB

+
+ +
diff --git a/tools/rum/rum-slicer.css b/tools/rum/rum-slicer.css index d6483323..9a693ee4 100644 --- a/tools/rum/rum-slicer.css +++ b/tools/rum/rum-slicer.css @@ -935,3 +935,44 @@ facet-sidebar[aria-disabled="true"] div.quick-filter { footer.footer-wrapper.appear { display: none; } + +#loading { + position: absolute; + width: 100%; + z-index: 10; + height: 100%; + opacity: 0.9; + background: var(--gray-100); +} + +#loading[aria-hidden="true"] { + display: none; +} + +#loading[aria-hidden="false"] { + display: unset; +} + +#loading .spinner { + position: relative; + top: calc(50% - 24px); + left: calc(50% - 24px); + width: 48px; + height: 48px; + border: 5px solid #FFF; + border-bottom-color: transparent; + border-radius: 50%; + display: inline-block; + box-sizing: border-box; + animation: rotation 1s linear infinite; +} + +@keyframes rotation { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/tools/rum/slicer.js b/tools/rum/slicer.js index a791a57c..3236ab53 100644 --- a/tools/rum/slicer.js +++ b/tools/rum/slicer.js @@ -290,14 +290,35 @@ async function loadData(config) { } export function updateState() { + // reload needed if data must be reloaded. This is the case if the domain or view / date changes + let reloadNeeded = false; + const url = new URL(window.location.href.split('?')[0]); const { searchParams } = new URL(window.location.href); + + if (searchParams.get('domain') !== DOMAIN) { + reloadNeeded = true; + } + url.searchParams.set('domain', DOMAIN); url.searchParams.set('filter', elems.filterInput.value); const viewConfig = elems.viewSelect.value; + + if (searchParams.get('view') !== viewConfig.value) { + reloadNeeded = true; + } + url.searchParams.set('view', viewConfig.value); if (viewConfig.value === 'custom') { + if (searchParams.get('startDate') !== viewConfig.from) { + reloadNeeded = true; + } + + if (searchParams.get('endDate') !== viewConfig.to) { + reloadNeeded = true; + } + url.searchParams.set('startDate', viewConfig.from); url.searchParams.set('endDate', viewConfig.to); } @@ -313,6 +334,25 @@ export function updateState() { window.history.replaceState({}, '', url); document.dispatchEvent(new CustomEvent('urlstatechange', { detail: url })); + + return reloadNeeded; +} + +export async function refresh(state = true) { + herochart.loading(); + elems.sidebar.disableFacets(); + + let reload = true; + if (state) { + reload = updateState(); + } + + if (reload) { + await loadData(elems.viewSelect.value); + } + + draw(); + elems.sidebar.enableFacets(); } const section = document.querySelector('main > div'); @@ -327,13 +367,12 @@ const io = new IntersectionObserver((entries) => { elems.sidebar = sidebar; sidebar.addEventListener('facetchange', () => { - // console.log('sidebar change'); - updateState(); - draw(); + refresh(); }); elems.viewSelect = document.getElementById('view'); elems.canvas = document.getElementById('time-series'); + elems.loading = document.getElementById('loading'); elems.timezoneElement = document.getElementById('timezone'); elems.lowDataWarning = document.getElementById('low-data-warning'); elems.incognito = document.querySelector('incognito-checkbox'); @@ -355,8 +394,7 @@ const io = new IntersectionObserver((entries) => { elems.incognito.addEventListener('change', async () => { loader.domainKey = elems.incognito.getAttribute('domainkey'); - await loadData(elems.viewSelect.value); - draw(); + refresh(false); }); herochart.render(); @@ -374,17 +412,15 @@ const io = new IntersectionObserver((entries) => { elems.timezoneElement.textContent = timezone; if (elems.incognito.getAttribute('domainkey')) { - loadData(elems.viewSelect.value).then(draw); + refresh(false); } elems.filterInput.addEventListener('input', () => { - updateState(); - draw(); + refresh(); }); elems.viewSelect.addEventListener('change', () => { - updateState(); - window.location.reload(); + refresh(); }); if (params.get('metrics') === 'all') {