Commit 907fc48b authored by Dhiraj Bodicherla's avatar Dhiraj Bodicherla

Fix empty charts in collapsed sections

Using resize observer to listen to chart containers
width. Removed other listeners to window resize
parent 3ca2042d
<script> <script>
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import { GlLink, GlButton, GlTooltip } from '@gitlab/ui'; import { GlLink, GlButton, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils'; import { roundOffFloat } from '~/lib/utils/common_utils';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { chartHeight, graphTypes, lineTypes, symbolSizes, dateFormats } from '../../constants'; import { chartHeight, graphTypes, lineTypes, symbolSizes, dateFormats } from '../../constants';
import { makeDataSeries } from '~/helpers/monitor_helper'; import { makeDataSeries } from '~/helpers/monitor_helper';
import { graphDataValidatorForValues } from '../../utils'; import { graphDataValidatorForValues } from '../../utils';
let debouncedResize;
export default { export default {
components: { components: {
GlAreaChart, GlAreaChart,
...@@ -22,6 +20,9 @@ export default { ...@@ -22,6 +20,9 @@ export default {
GlLink, GlLink,
Icon, Icon,
}, },
directives: {
GlResizeObserverDirective,
},
inheritAttrs: false, inheritAttrs: false,
props: { props: {
graphData: { graphData: {
...@@ -29,10 +30,6 @@ export default { ...@@ -29,10 +30,6 @@ export default {
required: true, required: true,
validator: graphDataValidatorForValues.bind(null, false), validator: graphDataValidatorForValues.bind(null, false),
}, },
containerWidth: {
type: Number,
required: true,
},
deploymentData: { deploymentData: {
type: Array, type: Array,
required: false, required: false,
...@@ -206,21 +203,13 @@ export default { ...@@ -206,21 +203,13 @@ export default {
return `${this.graphData.y_label}`; return `${this.graphData.y_label}`;
}, },
}, },
watch: {
containerWidth: 'onResize',
},
mounted() { mounted() {
const graphTitleEl = this.$refs.graphTitle; const graphTitleEl = this.$refs.graphTitle;
if (graphTitleEl && graphTitleEl.scrollWidth > graphTitleEl.offsetWidth) { if (graphTitleEl && graphTitleEl.scrollWidth > graphTitleEl.offsetWidth) {
this.showTitleTooltip = true; this.showTitleTooltip = true;
} }
}, },
beforeDestroy() {
window.removeEventListener('resize', debouncedResize);
},
created() { created() {
debouncedResize = debounceByAnimationFrame(this.onResize);
window.addEventListener('resize', debouncedResize);
this.setSvg('rocket'); this.setSvg('rocket');
this.setSvg('scroll-handle'); this.setSvg('scroll-handle');
}, },
...@@ -276,7 +265,7 @@ export default { ...@@ -276,7 +265,7 @@ export default {
</script> </script>
<template> <template>
<div class="prometheus-graph"> <div v-gl-resize-observer-directive="onResize" class="prometheus-graph">
<div class="prometheus-graph-header"> <div class="prometheus-graph-header">
<h5 <h5
ref="graphTitle" ref="graphTitle"
......
...@@ -22,12 +22,9 @@ import MonitorTimeSeriesChart from './charts/time_series.vue'; ...@@ -22,12 +22,9 @@ import MonitorTimeSeriesChart from './charts/time_series.vue';
import MonitorSingleStatChart from './charts/single_stat.vue'; import MonitorSingleStatChart from './charts/single_stat.vue';
import GraphGroup from './graph_group.vue'; import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import { sidebarAnimationDuration } from '../constants';
import TrackEventDirective from '~/vue_shared/directives/track_event'; import TrackEventDirective from '~/vue_shared/directives/track_event';
import { getTimeDiff, isValidDate, downloadCSVOptions, generateLinkToChartOptions } from '../utils'; import { getTimeDiff, isValidDate, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
let sidebarMutationObserver;
export default { export default {
components: { components: {
VueDraggable, VueDraggable,
...@@ -167,7 +164,6 @@ export default { ...@@ -167,7 +164,6 @@ export default {
data() { data() {
return { return {
state: 'gettingStarted', state: 'gettingStarted',
elWidth: 0,
formIsValid: null, formIsValid: null,
selectedTimeWindow: {}, selectedTimeWindow: {},
isRearrangingPanels: false, isRearrangingPanels: false,
...@@ -214,11 +210,6 @@ export default { ...@@ -214,11 +210,6 @@ export default {
projectPath: this.projectPath, projectPath: this.projectPath,
}); });
}, },
beforeDestroy() {
if (sidebarMutationObserver) {
sidebarMutationObserver.disconnect();
}
},
mounted() { mounted() {
if (!this.hasMetrics) { if (!this.hasMetrics) {
this.setGettingStartedEmptyState(); this.setGettingStartedEmptyState();
...@@ -239,13 +230,6 @@ export default { ...@@ -239,13 +230,6 @@ export default {
} else { } else {
this.fetchData(range); this.fetchData(range);
} }
sidebarMutationObserver = new MutationObserver(this.onSidebarMutation);
sidebarMutationObserver.observe(document.querySelector('.layout-page'), {
attributes: true,
childList: false,
subtree: false,
});
} }
}, },
methods: { methods: {
...@@ -306,11 +290,6 @@ export default { ...@@ -306,11 +290,6 @@ export default {
hideAddMetricModal() { hideAddMetricModal() {
this.$refs.addMetricModal.hide(); this.$refs.addMetricModal.hide();
}, },
onSidebarMutation() {
setTimeout(() => {
this.elWidth = this.$el.clientWidth;
}, sidebarAnimationDuration);
},
toggleRearrangingPanels() { toggleRearrangingPanels() {
this.isRearrangingPanels = !this.isRearrangingPanels; this.isRearrangingPanels = !this.isRearrangingPanels;
}, },
...@@ -503,7 +482,6 @@ export default { ...@@ -503,7 +482,6 @@ export default {
generateLink(groupData.group, graphData.title, graphData.y_label) generateLink(groupData.group, graphData.title, graphData.y_label)
" "
:graph-data="graphData" :graph-data="graphData"
:dashboard-width="elWidth"
:alerts-endpoint="alertsEndpoint" :alerts-endpoint="alertsEndpoint"
:prometheus-alerts-available="prometheusAlertsAvailable" :prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`" :index="`${index}-${graphIndex}`"
...@@ -520,7 +498,6 @@ export default { ...@@ -520,7 +498,6 @@ export default {
:graph-data="graphData" :graph-data="graphData"
:deployment-data="deploymentData" :deployment-data="deploymentData"
:thresholds="getGraphAlertValues(graphData.queries)" :thresholds="getGraphAlertValues(graphData.queries)"
:container-width="elWidth"
:project-path="projectPath" :project-path="projectPath"
group-id="monitor-time-series-chart" group-id="monitor-time-series-chart"
> >
......
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
<div v-if="showPanels" class="card prometheus-panel"> <div v-if="showPanels" class="card prometheus-panel">
<div class="card-header d-flex align-items-center"> <div class="card-header d-flex align-items-center">
<h4 class="flex-grow-1">{{ name }}</h4> <h4 class="flex-grow-1">{{ name }}</h4>
<a role="button" @click="collapse"> <a role="button" class="js-graph-group-toggle" @click="collapse">
<icon :size="16" :aria-label="__('Toggle collapse')" :name="caretIcon" /> <icon :size="16" :aria-label="__('Toggle collapse')" :name="caretIcon" />
</a> </a>
</div> </div>
......
...@@ -40,10 +40,6 @@ export default { ...@@ -40,10 +40,6 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
dashboardWidth: {
type: Number,
required: true,
},
index: { index: {
type: String, type: String,
required: false, required: false,
...@@ -103,7 +99,6 @@ export default { ...@@ -103,7 +99,6 @@ export default {
:deployment-data="deploymentData" :deployment-data="deploymentData"
:project-path="projectPath" :project-path="projectPath"
:thresholds="getGraphAlertValues(graphData.queries)" :thresholds="getGraphAlertValues(graphData.queries)"
:container-width="dashboardWidth"
group-id="monitor-area-chart" group-id="monitor-area-chart"
> >
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
......
---
title: Fix empty chart in collapsed sections
merge_request: 18699
author:
type: fixed
...@@ -539,42 +539,67 @@ describe('Dashboard', () => { ...@@ -539,42 +539,67 @@ describe('Dashboard', () => {
}); });
}); });
describe('when the window resizes', () => { describe('responds to window resizes', () => {
let promPanel;
let promGroup;
let panelToggle;
let chart;
beforeEach(() => { beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse); mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('sets elWidth to page width when the sidebar is resized', done => {
component = new DashboardComponent({ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
propsData: { propsData: {
...propsData, ...propsData,
hasMetrics: true, hasMetrics: true,
showPanels: false, showPanels: true,
}, },
store, store,
}); });
expect(component.elWidth).toEqual(0); component.$store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpoint: false,
});
const pageLayoutEl = document.querySelector('.layout-page'); component.$store.commit(
pageLayoutEl.classList.add('page-with-icon-sidebar'); `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
Vue.nextTick() component.$store.commit(
.then(() => { `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
jasmine.clock().tick(1000); singleGroupResponse,
return Vue.nextTick(); );
})
.then(() => { component.$store.commit(
expect(component.elWidth).toEqual(pageLayoutEl.clientWidth); `monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
done(); dashboardGitResponse,
}) );
.catch(done.fail);
return Vue.nextTick().then(() => {
promPanel = component.$el.querySelector('.prometheus-panel');
promGroup = promPanel.querySelector('.prometheus-graph-group');
panelToggle = promPanel.querySelector('.js-graph-group-toggle');
chart = promGroup.querySelector('.position-relative svg');
});
});
it('setting chart size to zero when panel group is hidden', () => {
expect(promGroup.style.display).toBe('');
expect(chart.clientWidth).toBeGreaterThan(0);
panelToggle.click();
return Vue.nextTick().then(() => {
expect(promGroup.style.display).toBe('none');
expect(chart.clientWidth).toBe(0);
promPanel.style.width = '500px';
});
});
it('expanding chart panel group after resize displays chart', () => {
panelToggle.click();
expect(chart.clientWidth).toBeGreaterThan(0);
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment