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') {