Skip to content

Commit

Permalink
events and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomivirkki committed Sep 11, 2024
1 parent b3a98a2 commit b813781
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 8 deletions.
14 changes: 14 additions & 0 deletions dev/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@
console.log('dashboard-item-reorder-end');
console.log('items after reorder', e.target.items);
});

dashboard.addEventListener('dashboard-item-resize-start', (e) => {
console.log('dashboard-item-resize-start');
});

dashboard.addEventListener('dashboard-item-drag-resize', (e) => {
console.log('dashboard-item-drag-resize', e.detail);
// e.preventDefault();
});

dashboard.addEventListener('dashboard-item-resize-end', (e) => {
console.log('dashboard-item-resize-end');
console.log('item after resize', e.detail);
});
</script>
</head>

Expand Down
29 changes: 29 additions & 0 deletions packages/dashboard/src/vaadin-dashboard.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,41 @@ export type DashboardItemDragReorderEvent<TItem extends DashboardItem> = CustomE
targetIndex: number;
}>;

/**
* Fired when item resizing starts
*/
export type DashboardItemResizeStartEvent<TItem extends DashboardItem> = CustomEvent<{
item: TItem;
}>;

/**
* Fired when item resizing ends
*/
export type DashboardItemResizeEndEvent<TItem extends DashboardItem> = CustomEvent<{
item: TItem;
}>;

/**
* Fired when an item will be resized by dragging
*/
export type DashboardItemDragResizeEvent<TItem extends DashboardItem> = CustomEvent<{
item: TItem;
colspan: number;
rowspan: number;
}>;

export interface DashboardCustomEventMap<TItem extends DashboardItem> {
'dashboard-item-reorder-start': DashboardItemReorderStartEvent;

'dashboard-item-reorder-end': DashboardItemReorderEndEvent;

'dashboard-item-drag-reorder': DashboardItemDragReorderEvent<TItem>;

'dashboard-item-resize-start': DashboardItemResizeStartEvent<TItem>;

'dashboard-item-resize-end': DashboardItemResizeEndEvent<TItem>;

'dashboard-item-drag-resize': DashboardItemDragResizeEvent<TItem>;
}

export type DashboardEventMap<TItem extends DashboardItem> = DashboardCustomEventMap<TItem> & HTMLElementEventMap;
Expand Down
27 changes: 27 additions & 0 deletions packages/dashboard/src/vaadin-dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import { WidgetResizeController } from './widget-resize-controller.js';
* @fires {CustomEvent} dashboard-item-drag-reorder - Fired when an items will be reordered by dragging
* @fires {CustomEvent} dashboard-item-reorder-start - Fired when item reordering starts
* @fires {CustomEvent} dashboard-item-reorder-end - Fired when item reordering ends
* @fires {CustomEvent} dashboard-item-drag-resize - Fired when an item will be resized by dragging
* @fires {CustomEvent} dashboard-item-resize-start - Fired when item resizing starts
* @fires {CustomEvent} dashboard-item-resize-end - Fired when item resizing ends
*
* @customElement
* @extends HTMLElement
Expand Down Expand Up @@ -106,6 +109,12 @@ class Dashboard extends ControllerMixin(DashboardLayoutMixin(ElementMixin(Themab
this.__widgetResizeController = new WidgetResizeController(this);
}

/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
this.__widgetResizeController.cleanup();
}

/** @protected */
ready() {
super.ready();
Expand Down Expand Up @@ -189,6 +198,24 @@ class Dashboard extends ControllerMixin(DashboardLayoutMixin(ElementMixin(Themab
*
* @event dashboard-item-drag-reorder
*/

/**
* Fired when item resizing starts
*
* @event dashboard-item-resize-start
*/

/**
* Fired when item resizing ends
*
* @event dashboard-item-resize-end
*/

/**
* Fired when an item will be resized by dragging
*
* @event dashboard-item-drag-resize
*/
}

defineCustomElement(Dashboard);
Expand Down
31 changes: 23 additions & 8 deletions packages/dashboard/src/widget-resize-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class WidgetResizeController extends EventTarget {
this.host.$.grid.toggleAttribute('resizing', false);

this.__resizedElementRemoveObserver.disconnect();
document.removeEventListener('touchmove', this.__touchMoveCancelListener);
this.cleanup();

this.host.dispatchEvent(new CustomEvent('dashboard-item-resize-end'));
}
Expand All @@ -126,14 +126,25 @@ export class WidgetResizeController extends EventTarget {
}

/** @private */
__updateResizedItem(colspan, rowspan) {
if (this.resizedItem.colspan !== colspan || this.resizedItem.rowspan !== rowspan) {
this.resizedItem.colspan = colspan;
this.resizedItem.rowspan = rowspan;
this.host.dispatchEvent(new CustomEvent('dashboard-item-resize', { detail: { item: this.resizedItem } }));
this.host.items = [...this.host.items];
requestAnimationFrame(() => this.__updateWidgetStyles());
__updateResizedItem(colspan = 1, rowspan = 1) {
if (this.resizedItem.colspan === colspan && this.resizedItem.rowspan === rowspan) {
return;
}

const resizeEvent = new CustomEvent('dashboard-item-drag-resize', {
detail: { item: this.resizedItem, colspan, rowspan },
cancelable: true,
});

// Dispatch the resize event and resize items if the event is not canceled
if (!this.host.dispatchEvent(resizeEvent)) {
return;
}

this.resizedItem.colspan = colspan;
this.resizedItem.rowspan = rowspan;
this.host.items = [...this.host.items];
requestAnimationFrame(() => this.__updateWidgetStyles());
}

/** @private */
Expand All @@ -150,4 +161,8 @@ export class WidgetResizeController extends EventTarget {
this.host.appendChild(this.__resizedElement);
}
}

cleanup() {
document.removeEventListener('touchmove', this.__touchMoveCancelListener);
}
}
70 changes: 70 additions & 0 deletions packages/dashboard/test/dashboard-widget-resizing.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect } from '@vaadin/chai-plugins';
import { fixtureSync, nextFrame } from '@vaadin/testing-helpers';
import sinon from 'sinon';
import '../vaadin-dashboard.js';
import type { Dashboard, DashboardItem } from '../vaadin-dashboard.js';
import {
Expand Down Expand Up @@ -228,6 +229,75 @@ describe('dashboard - widget resizing', () => {
]);
});

it('should dispatch an item resize start event', async () => {
const resizeStartSpy = sinon.spy();
dashboard.addEventListener('dashboard-item-resize-start', resizeStartSpy);
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();

expect(resizeStartSpy).to.have.been.calledOnce;
});

it('should dispatch an item drag resize event', async () => {
const resizeSpy = sinon.spy();
dashboard.addEventListener('dashboard-item-drag-resize', resizeSpy);
dashboard.addEventListener('dashboard-item-drag-resize', (e) => e.preventDefault());
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
await nextFrame();

expect(resizeSpy).to.have.been.calledOnce;
expect(resizeSpy.getCall(0).args[0].detail).to.deep.equal({
item: { id: 0 },
colspan: 2,
rowspan: 1,
});
});

it('should not resize if the drag resize event is cancelled', async () => {
dashboard.addEventListener('dashboard-item-drag-resize', (e) => e.preventDefault());
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
await nextFrame();
// prettier-ignore
expectLayout(dashboard, [
[0, 1],
]);
});

it('should dispatch an item resize end event', async () => {
const resizeEndSpy = sinon.spy();
dashboard.addEventListener('dashboard-item-resize-end', resizeEndSpy);
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
fireResizeEnd(dashboard);
await nextFrame();

expect(resizeEndSpy).to.have.been.calledOnce;
});

it('should cancel touchmove events while resizing', async () => {
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
const touchmove = new TouchEvent('touchmove', { cancelable: true, bubbles: true });
document.dispatchEvent(touchmove);

expect(touchmove.defaultPrevented).to.be.true;
});

it('should not cancel touchmove events after resizing has finished', async () => {
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
fireResizeEnd(dashboard);

const touchmove = new TouchEvent('touchmove', { cancelable: true, bubbles: true });
document.dispatchEvent(touchmove);

expect(touchmove.defaultPrevented).to.be.false;
});

// Make sure the original resized element is restored in the host.
// Otherwise, "track" event would stop working.
describe('ensure track event', () => {
Expand Down
19 changes: 19 additions & 0 deletions packages/dashboard/test/typings/dashboard.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import type {
Dashboard,
DashboardItem,
DashboardItemDragReorderEvent,
DashboardItemDragResizeEvent,
DashboardItemReorderEndEvent,
DashboardItemReorderStartEvent,
DashboardItemResizeEndEvent,
DashboardItemResizeStartEvent,
DashboardRenderer,
DashboardSectionItem,
} from '../../vaadin-dashboard.js';
Expand Down Expand Up @@ -57,6 +60,22 @@ narrowedDashboard.addEventListener('dashboard-item-drag-reorder', (event) => {
assertType<number>(event.detail.targetIndex);
});

narrowedDashboard.addEventListener('dashboard-item-resize-start', (event) => {
assertType<DashboardItemResizeStartEvent<TestDashboardItem>>(event);
});

narrowedDashboard.addEventListener('dashboard-item-resize-end', (event) => {
assertType<DashboardItemResizeEndEvent<TestDashboardItem>>(event);
assertType<TestDashboardItem>(event.detail.item);
});

narrowedDashboard.addEventListener('dashboard-item-drag-resize', (event) => {
assertType<DashboardItemDragResizeEvent<TestDashboardItem>>(event);
assertType<TestDashboardItem>(event.detail.item);
assertType<number>(event.detail.colspan);
assertType<number>(event.detail.rowspan);
});

/* DashboardLayout */
const layout = document.createElement('vaadin-dashboard-layout');
assertType<DashboardLayout>(layout);
Expand Down

0 comments on commit b813781

Please sign in to comment.