Commit 2327dd84 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'resize-vuln-graph' into 'master'

Resize vuln graph

See merge request gitlab-org/gitlab-ee!10028
parents bdc3e121 6867dc78
......@@ -41,6 +41,9 @@ export default class ContextualSidebar {
this.toggleCollapsedSidebar(value, true);
}
});
this.$page.on('transitionstart transitionend', () => {
$(document).trigger('content.resize');
});
$(window).on('resize', () => _.debounce(this.render(), 100));
}
......
<script>
import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
import $ from 'jquery';
export default {
data() {
return {
width: 0,
height: 0,
};
},
beforeDestroy() {
this.contentResizeHandler.off('content.resize', this.debouncedResize);
window.removeEventListener('resize', this.debouncedResize);
},
created() {
this.debouncedResize = debounceByAnimationFrame(this.onResize);
// Handle when we explicictly trigger a custom resize event
this.contentResizeHandler = $(document).on('content.resize', this.debouncedResize);
// Handle window resize
window.addEventListener('resize', this.debouncedResize);
},
methods: {
onResize() {
// Slot dimensions
const { clientWidth, clientHeight } = this.$refs.chartWrapper;
this.width = clientWidth;
this.height = clientHeight;
},
},
};
</script>
<template>
<div ref="chartWrapper">
<slot :width="width" :height="height"> </slot>
</div>
</template>
......@@ -7,6 +7,7 @@ import ChartTooltip from './vulnerability_chart_tooltip.vue';
import ChartButtons from './vulnerability_chart_buttons.vue';
import { DAY_IN_MS, DAYS } from '../store/modules/vulnerabilities/constants';
import { SEVERITY_LEVELS } from '../store/constants';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
export default {
name: 'VulnerabilityChart',
......@@ -14,6 +15,7 @@ export default {
GlChart,
ChartTooltip,
ChartButtons,
ResizableChartContainer,
},
DAYS,
data: () => ({
......@@ -189,7 +191,15 @@ export default {
<div class="vulnerabilities-chart">
<div class="vulnerabilities-chart-wrapper">
<gl-chart :options="options" :disable-theme="true" />
<resizable-chart-container>
<gl-chart
slot-scope="{ width, height }"
:options="options"
:width="width"
:height="height"
:disable-theme="true"
/>
</resizable-chart-container>
<chart-tooltip
v-show="false"
ref="tooltip"
......
......@@ -2,22 +2,5 @@ $trans-white: rgba(255, 255, 255, 0);
.vulnerabilities-chart-wrapper {
-webkit-overflow-scrolling: touch;
overflow: auto;
}
@media screen and (max-width: 1240px) {
.vulnerabilities-chart {
position: relative;
}
.vulnerabilities-chart::after {
background-image: linear-gradient(to right, $trans-white, $gl-gray-350);
bottom: 0;
content: '';
height: 305px;
position: absolute;
right: -1px;
top: 10px;
width: 32px;
}
}
---
title: Dynamically resize security group dashboard vuln graph
merge_request: 10028
author:
type: changed
import Vue from 'vue';
import MockAdapater from 'axios-mock-adapter';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import component from 'ee/security_dashboard/components/vulnerability_chart.vue';
import createStore from 'ee/security_dashboard/store';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import waitForPromises from 'spec/helpers/wait_for_promises';
import { mount } from '@vue/test-utils';
import { resetStore } from '../helpers';
import mockDataVulnerabilitiesHistory from '../store/vulnerabilities/data/mock_data_vulnerabilities_history.json';
......@@ -15,26 +14,26 @@ describe('Vulnerabilities Chart', () => {
const vulnerabilitiesHistoryEndpoint = '/vulnerabilitiesEndpoint.json';
let store;
let mock;
let vm;
let wrapper;
beforeEach(() => {
store = createStore();
store.state.vulnerabilities.vulnerabilitiesHistoryEndpoint = vulnerabilitiesHistoryEndpoint;
mock = new MockAdapater(axios);
mock = new MockAdapter(axios);
mock.onGet(vulnerabilitiesHistoryEndpoint).replyOnce(200, mockDataVulnerabilitiesHistory);
vm = mountComponentWithStore(Component, { store });
wrapper = mount(Component, { store, sync: false });
});
afterEach(() => {
resetStore(store);
vm.$destroy();
wrapper.destroy();
mock.restore();
});
it('should render the e-chart instance', done => {
waitForPromises()
Vue.nextTick()
.then(() => {
expect(vm.$el.querySelector('[_echarts_instance_]')).not.toBeNull();
expect(wrapper.find('[_echarts_instance_]')).not.toBeNull();
done();
})
.catch(done.fail);
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Resizable Chart Container renders the component 1`] = `
<div>
<div
class="slot"
>
<span
class="width"
>
0
</span>
<span
class="height"
>
0
</span>
</div>
</div>
`;
import Vue from 'vue';
import { mount } from '@vue/test-utils';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
import $ from 'jquery';
jest.mock('~/lib/utils/common_utils', () => ({
debounceByAnimationFrame(callback) {
return jest.spyOn({ callback }, 'callback');
},
}));
describe('Resizable Chart Container', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(ResizableChartContainer, {
attachToDocument: true,
scopedSlots: {
default: `
<div class="slot" slot-scope="{ width, height }">
<span class="width">{{width}}</span>
<span class="height">{{height}}</span>
</div>
`,
},
});
});
afterEach(() => {
wrapper.destroy();
});
it('renders the component', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('updates the slot width and height props', () => {
const width = 1920;
const height = 1080;
// JSDOM mocks and sets clientWidth/clientHeight to 0 so we set manually
wrapper.vm.$refs.chartWrapper = { clientWidth: width, clientHeight: height };
$(document).trigger('content.resize');
return Vue.nextTick().then(() => {
const widthNode = wrapper.find('.slot > .width');
const heightNode = wrapper.find('.slot > .height');
expect(parseInt(widthNode.text(), 10)).toEqual(width);
expect(parseInt(heightNode.text(), 10)).toEqual(height);
});
});
it('calls onResize on manual resize', () => {
$(document).trigger('content.resize');
expect(wrapper.vm.debouncedResize).toHaveBeenCalled();
});
it('calls onResize on page resize', () => {
window.dispatchEvent(new Event('resize'));
expect(wrapper.vm.debouncedResize).toHaveBeenCalled();
});
});
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