Commit eea793bc authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'fix-design-overlay-commenting' into 'master'

Fix incorrect repositioning of design comment pins when mouse leaves viewport

See merge request gitlab-org/gitlab!29464
parents 438d67c1 e3350d29
...@@ -219,7 +219,7 @@ export default { ...@@ -219,7 +219,7 @@ export default {
type="button" type="button"
class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button" class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
data-qa-selector="design_image_button" data-qa-selector="design_image_button"
@click="setNewNoteCoordinates({ x: $event.offsetX, y: $event.offsetY })" @mouseup="setNewNoteCoordinates({ x: $event.offsetX, y: $event.offsetY })"
></button> ></button>
<design-note-pin <design-note-pin
v-for="(note, index) in notes" v-for="(note, index) in notes"
......
...@@ -46,8 +46,8 @@ export default { ...@@ -46,8 +46,8 @@ export default {
height: 0, height: 0,
}, },
initialLoad: true, initialLoad: true,
startDragPosition: null,
lastDragPosition: null, lastDragPosition: null,
isDraggingDesign: false,
}; };
}, },
computed: { computed: {
...@@ -62,9 +62,6 @@ export default { ...@@ -62,9 +62,6 @@ export default {
cursor: this.isDraggingDesign ? 'grabbing' : undefined, cursor: this.isDraggingDesign ? 'grabbing' : undefined,
}; };
}, },
isDraggingDesign() {
return Boolean(this.lastDragPosition);
},
}, },
beforeDestroy() { beforeDestroy() {
const { presentationViewport } = this.$refs; const { presentationViewport } = this.$refs;
...@@ -219,15 +216,14 @@ export default { ...@@ -219,15 +216,14 @@ export default {
onPresentationMousedown({ clientX, clientY }) { onPresentationMousedown({ clientX, clientY }) {
if (!this.isDesignOverflowing()) return; if (!this.isDesignOverflowing()) return;
this.startDragPosition = { this.lastDragPosition = {
x: clientX, x: clientX,
y: clientY, y: clientY,
}; };
this.lastDragPosition = { ...this.startDragPosition };
}, },
onPresentationMousemove({ clientX, clientY }) { onPresentationMousemove({ clientX, clientY }) {
if (!this.lastDragPosition) return; if (!this.lastDragPosition) return;
this.isDraggingDesign = true;
const { presentationViewport } = this.$refs; const { presentationViewport } = this.$refs;
if (!presentationViewport) return; if (!presentationViewport) return;
...@@ -242,15 +238,9 @@ export default { ...@@ -242,15 +238,9 @@ export default {
y: clientY, y: clientY,
}; };
}, },
onPresentationMouseup({ offsetX, offsetY }) { onPresentationMouseup() {
if (
this.startDragPosition?.x === this.lastDragPosition?.x &&
this.startDragPosition?.y === this.lastDragPosition?.y
) {
this.openCommentForm({ x: offsetX, y: offsetY });
}
this.lastDragPosition = null; this.lastDragPosition = null;
this.isDraggingDesign = false;
}, },
isDesignOverflowing() { isDesignOverflowing() {
const { presentationContainer } = this.$refs; const { presentationContainer } = this.$refs;
......
---
title: Fix incorrect repositioning of design comment pins when mouse leaves viewport
merge_request: 29464
author:
type: fixed
...@@ -61,7 +61,7 @@ describe('Design overlay component', () => { ...@@ -61,7 +61,7 @@ describe('Design overlay component', () => {
wrapper wrapper
.find('.image-diff-overlay-add-comment') .find('.image-diff-overlay-add-comment')
.trigger('click', { offsetX: newCoordinates.x, offsetY: newCoordinates.y }); .trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toEqual([ expect(wrapper.emitted('openCommentForm')).toEqual([
[{ x: newCoordinates.x, y: newCoordinates.y }], [{ x: newCoordinates.x, y: newCoordinates.y }],
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import DesignPresentation from 'ee/design_management/components/design_presentation.vue'; import DesignPresentation from 'ee/design_management/components/design_presentation.vue';
import DesignOverlay from 'ee/design_management/components/design_overlay.vue';
const mockOverlayData = { const mockOverlayData = {
overlayDimensions: { overlayDimensions: {
...@@ -18,6 +19,7 @@ describe('Design management design presentation component', () => { ...@@ -18,6 +19,7 @@ describe('Design management design presentation component', () => {
function createComponent( function createComponent(
{ image, imageName, discussions = [], isAnnotating = false } = {}, { image, imageName, discussions = [], isAnnotating = false } = {},
data = {}, data = {},
stubs = {},
) { ) {
wrapper = shallowMount(DesignPresentation, { wrapper = shallowMount(DesignPresentation, {
propsData: { propsData: {
...@@ -26,11 +28,15 @@ describe('Design management design presentation component', () => { ...@@ -26,11 +28,15 @@ describe('Design management design presentation component', () => {
discussions, discussions,
isAnnotating, isAnnotating,
}, },
stubs,
}); });
wrapper.setData(data); wrapper.setData(data);
wrapper.element.scrollTo = jest.fn();
} }
const findOverlayCommentButton = () => wrapper.find('.image-diff-overlay-add-comment');
/** /**
* Spy on $refs and mock given values * Spy on $refs and mock given values
* @param {Object} viewportDimensions {width, height} * @param {Object} viewportDimensions {width, height}
...@@ -70,12 +76,17 @@ describe('Design management design presentation component', () => { ...@@ -70,12 +76,17 @@ describe('Design management design presentation component', () => {
mouseup: 'mouseup', mouseup: 'mouseup',
}; };
wrapper.trigger(event.mousedown, { const addCommentOverlay = findOverlayCommentButton();
// triggering mouse events on this element best simulates
// reality, as it is the lowest-level node that needs to
// respond to mouse events
addCommentOverlay.trigger(event.mousedown, {
clientX: startCoords.clientX, clientX: startCoords.clientX,
clientY: startCoords.clientY, clientY: startCoords.clientY,
}); });
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
wrapper.trigger(event.mousemove, { addCommentOverlay.trigger(event.mousemove, {
clientX: endCoords.clientX, clientX: endCoords.clientX,
clientY: endCoords.clientY, clientY: endCoords.clientY,
}); });
...@@ -425,52 +436,20 @@ describe('Design management design presentation component', () => { ...@@ -425,52 +436,20 @@ describe('Design management design presentation component', () => {
}); });
}); });
describe('onPresentationMouseUp when design is overflowing', () => { describe('when design is overflowing', () => {
it('does not open a comment form if design was dragged', () => { beforeEach(() => {
const startDragPosition = { x: 1, y: 1 };
const lastDragPosition = { x: 2, y: 2 };
createComponent({}, { startDragPosition, lastDragPosition });
wrapper.vm.onPresentationMouseup({ offsetX: 2, offsetY: 2 });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toBeFalsy();
});
});
it('opens a comment form if design was not dragged', () => {
const startDragPosition = { x: 1, y: 1 };
const lastDragPosition = { x: 1, y: 1 };
createComponent(
{},
{
startDragPosition,
lastDragPosition,
...mockOverlayData,
},
);
wrapper.vm.onPresentationMouseup({ offsetX: 2, offsetY: 2 });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toBeDefined();
});
});
});
describe('when clicking and dragging', () => {
it.each`
description | useTouchEvents
${'with touch events'} | ${true}
${'without touch events'} | ${false}
`('calls scrollTo with correct arguments $description', ({ useTouchEvents }) => {
createComponent( createComponent(
{ {
image: 'test.jpg', image: 'test.jpg',
imageName: 'test', imageName: 'test',
}, },
mockOverlayData, mockOverlayData,
{
'design-overlay': DesignOverlay,
},
); );
// mock a design that overflows
mockRefDimensions( mockRefDimensions(
wrapper.vm.$refs.presentationContainer, wrapper.vm.$refs.presentationContainer,
{ width: 10, height: 10 }, { width: 10, height: 10 },
...@@ -478,15 +457,53 @@ describe('Design management design presentation component', () => { ...@@ -478,15 +457,53 @@ describe('Design management design presentation component', () => {
0, 0,
0, 0,
); );
});
wrapper.element.scrollTo = jest.fn(); it('opens a comment form if design was not dragged', () => {
return clickDragExplore( const addCommentOverlay = findOverlayCommentButton();
{ clientX: 0, clientY: 0 }, const startCoords = {
{ clientX: 10, clientY: 10 }, clientX: 1,
{ useTouchEvents }, clientY: 1,
).then(() => { };
expect(wrapper.element.scrollTo).toHaveBeenCalledTimes(1);
expect(wrapper.element.scrollTo).toHaveBeenCalledWith(-10, -10); addCommentOverlay.trigger('mousedown', {
clientX: startCoords.clientX,
clientY: startCoords.clientY,
});
return wrapper.vm
.$nextTick()
.then(() => {
addCommentOverlay.trigger('mouseup');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(wrapper.emitted('openCommentForm')).toBeDefined();
});
});
describe('when clicking and dragging', () => {
it.each`
description | useTouchEvents
${'with touch events'} | ${true}
${'without touch events'} | ${false}
`('calls scrollTo with correct arguments $description', ({ useTouchEvents }) => {
return clickDragExplore(
{ clientX: 0, clientY: 0 },
{ clientX: 10, clientY: 10 },
{ useTouchEvents },
).then(() => {
expect(wrapper.element.scrollTo).toHaveBeenCalledTimes(1);
expect(wrapper.element.scrollTo).toHaveBeenCalledWith(-10, -10);
});
});
it('does not open a comment form', () => {
return clickDragExplore({ clientX: 0, clientY: 0 }, { clientX: 10, clientY: 10 }).then(
() => {
expect(wrapper.emitted('openCommentForm')).toBeFalsy();
},
);
}); });
}); });
}); });
......
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