[IMP] web: prevent action swiper from being triggered by fullcalendar

Currently in calendar views in mobile it is possible to create events selecting
the time of the event by dragging. However, in calendar we also have the action
swiper responsible for moving between weeks when swiping close to the borders.
The issue is that when trying to create events by dragging close to the border
will cause the action swiper to trigger a swipe, therefore switching to the
next week. This commit fixes this by adding a swipeInvalid prop to the action
swiper that will be checked during the touch move event handler. If the
swipeInvalid is executed at any move and returns true, the swipe is cancelled.

task-3635841

closes odoo/odoo#148541

X-original-commit: 7772b17f226ddb99060b51d6b337e5f5106b5c25
Signed-off-by: Arnaud Joset (arj) <arj@odoo.com>
Signed-off-by: Leonardo Pavan Rocha <lpr@odoo.com>
This commit is contained in:
Leonardo Pavan Rocha
2024-01-10 06:12:28 +00:00
parent 796cb061d0
commit c6f8b62196
3 changed files with 64 additions and 0 deletions
@@ -100,6 +100,10 @@ export class ActionSwiper extends Component {
*/
_onTouchMoveSwipe(ev) {
if (this.state.isSwiping) {
if (this.props.swipeInvalid && this.props.swipeInvalid()) {
this.state.isSwiping = false;
return;
}
const { onLeftSwipe, onRightSwipe } = this.localizedProps;
this.swipedDistance = clamp(
ev.touches[0].clientX - this.startX,
@@ -209,6 +213,7 @@ ActionSwiper.props = {
animationOnMove: { type: Boolean, optional: true },
animationType: { type: String, optional: true },
swipeDistanceRatio: { type: Number, optional: true },
swipeInvalid: { type: Function, optional: true },
};
ActionSwiper.defaultProps = {
@@ -24,6 +24,7 @@ export class CalendarRenderer extends Component {
animationOnMove: false,
animationType: "forwards",
swipeDistanceRatio: 6,
swipeInvalid: () => Boolean(document.querySelector(".o_event.fc-mirror")),
};
}
}
@@ -863,4 +863,62 @@ QUnit.module("ActionSwiper", ({ beforeEach }) => {
);
}
);
QUnit.test("swipeInvalid prop prevents swiping", async (assert) => {
assert.expect(3);
const { execRegisteredTimeouts } = mockTimeout();
class Parent extends Component {
onRightSwipe() {
assert.step("onRightSwipe");
}
swipeInvalid() {
assert.step("swipeInvalid");
return true;
}
}
Parent.components = { ActionSwiper };
Parent.template = xml`
<div class="d-flex">
<ActionSwiper onRightSwipe = "{
action: onRightSwipe,
icon: 'fa-circle',
bgColor: 'bg-warning',
}" swipeInvalid = "swipeInvalid">
<div class="target-component" style="width: 200px; height: 80px">Test</div>
</ActionSwiper>
</div>
`;
await mount(Parent, target, { env });
const swiper = target.querySelector(".o_actionswiper");
const targetContainer = target.querySelector(".o_actionswiper_target_container");
// Touch ends once the half of the distance has been crossed
await triggerEvent(target, ".o_actionswiper", "touchstart", {
touches: [
{
identifier: 0,
clientX: swiper.clientWidth / 2,
clientY: 0,
target: target,
},
],
});
await triggerEvent(target, ".o_actionswiper", "touchmove", {
touches: [
{
identifier: 0,
clientX: swiper.clientWidth + 1,
clientY: 0,
target: target,
},
],
});
await triggerEvent(target, ".o_actionswiper", "touchend", {});
execRegisteredTimeouts();
await nextTick();
assert.ok(
!targetContainer.style.transform.includes("translateX"),
"target doesn't have translateX after action is performed"
);
assert.verifySteps(["swipeInvalid"]);
});
});