From fe6ae727ce24be96e67dbcd6b165e08a6be65c56 Mon Sep 17 00:00:00 2001 From: Philipp Fromme Date: Wed, 21 Feb 2024 13:49:42 +0100 Subject: [PATCH 1/2] feat(popup-menu): add ability to refresh without reopening Closes #804 --- lib/features/popup-menu/PopupMenu.js | 35 +++++++- .../spec/features/popup-menu/PopupMenuSpec.js | 80 ++++++++++++++++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/lib/features/popup-menu/PopupMenu.js b/lib/features/popup-menu/PopupMenu.js index 69c996926..1b6892ea0 100644 --- a/lib/features/popup-menu/PopupMenu.js +++ b/lib/features/popup-menu/PopupMenu.js @@ -101,7 +101,7 @@ PopupMenu.prototype._render = function() { const { position: _position, - className, + providerId: className, entries, headerEntries, emptyPlaceholder, @@ -179,7 +179,7 @@ PopupMenu.prototype.open = function(target, providerId, position, options) { this._current = { position, - className: providerId, + providerId, target, entries, headerEntries, @@ -195,6 +195,37 @@ PopupMenu.prototype.open = function(target, providerId, position, options) { this._render(); }; +/** + * Refresh the popup menu entries without changing the target or position. + */ +PopupMenu.prototype.refresh = function() { + if (!this.isOpen()) { + return; + } + + const { + target, + providerId + } = this._current; + + const { + entries, + headerEntries, + emptyPlaceholder + } = this._getContext(target, providerId); + + this._current = { + ...this._current, + entries, + headerEntries, + emptyPlaceholder + }; + + this._emit('refresh'); + + this._render(); +}; + PopupMenu.prototype._getContext = function(target, provider) { diff --git a/test/spec/features/popup-menu/PopupMenuSpec.js b/test/spec/features/popup-menu/PopupMenuSpec.js index ce82781e3..18f907b3e 100755 --- a/test/spec/features/popup-menu/PopupMenuSpec.js +++ b/test/spec/features/popup-menu/PopupMenuSpec.js @@ -558,6 +558,85 @@ describe('features/popup-menu', function() { }); + describe('#refresh', function() { + + it('should refresh', inject(function(eventBus, popupMenu) { + + // given + var refreshSpy = sinon.spy(); + + eventBus.on('popupMenu.refresh', refreshSpy); + + var dynamicMenuProvider = { + getPopupMenuEntries: function() { + return { + foo: { label: 'Foo' }, + bar: { label: 'Bar' } + }; + }, + getHeaderEntries: function() { + return { + foo: { id: 'foo', label: 'Foo' }, + bar: { id: 'bar', label: 'Bar' } + }; + } + }; + + popupMenu.registerProvider('menu', dynamicMenuProvider); + + popupMenu.open({}, 'menu', { x: 100, y: 100 }); + + expect(popupMenu._current).to.exist; + expect(popupMenu._current.entries).to.have.keys('foo', 'bar'); + expect(popupMenu._current.entries).not.to.have.keys('baz'); + expect(popupMenu._current.headerEntries).to.have.keys('foo', 'bar'); + expect(popupMenu._current.headerEntries).not.to.have.keys('baz'); + + // when + dynamicMenuProvider.getPopupMenuEntries = function() { + return { + foo: { label: 'Foo' }, + bar: { label: 'Bar' }, + baz: { label: 'Baz' } + }; + }; + + dynamicMenuProvider.getHeaderEntries = function() { + return { + foo: { id: 'foo', label: 'Foo' }, + bar: { id: 'bar', label: 'Bar' }, + baz: { id: 'baz', label: 'Baz' } + }; + }; + + popupMenu.refresh(); + + // then + expect(refreshSpy).to.have.been.calledOnce; + + expect(popupMenu._current).to.exist; + expect(popupMenu._current.entries).to.have.keys('foo', 'bar', 'baz'); + expect(popupMenu._current.headerEntries).to.have.keys('foo', 'bar', 'baz'); + })); + + + it('should not refresh', inject(function(eventBus, popupMenu) { + + // given + var refreshSpy = sinon.spy(); + + eventBus.on('popupMenu.refresh', refreshSpy); + + // when + popupMenu.refresh(); + + // then + expect(refreshSpy).not.to.have.been.called; + })); + + }); + + describe('#close', function() { beforeEach(inject(async function(eventBus, popupMenu) { @@ -842,7 +921,6 @@ describe('features/popup-menu', function() { }); })); - }); From c0de9c447ed46e5e6c7e1c73bf2256eae2c99d15 Mon Sep 17 00:00:00 2001 From: Philipp Fromme Date: Wed, 21 Feb 2024 14:55:56 +0100 Subject: [PATCH 2/2] feat(popup-menu): refresh on `element.changed` --- lib/features/popup-menu/PopupMenu.js | 2 +- .../spec/features/popup-menu/PopupMenuSpec.js | 49 +++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/features/popup-menu/PopupMenu.js b/lib/features/popup-menu/PopupMenu.js index 1b6892ea0..89e406045 100644 --- a/lib/features/popup-menu/PopupMenu.js +++ b/lib/features/popup-menu/PopupMenu.js @@ -85,7 +85,7 @@ export default function PopupMenu(config, eventBus, canvas) { const element = this.isOpen() && this._current.target; if (event.element === element) { - this._render(); + this.refresh(); } }); diff --git a/test/spec/features/popup-menu/PopupMenuSpec.js b/test/spec/features/popup-menu/PopupMenuSpec.js index 18f907b3e..1a5e66004 100755 --- a/test/spec/features/popup-menu/PopupMenuSpec.js +++ b/test/spec/features/popup-menu/PopupMenuSpec.js @@ -250,7 +250,6 @@ describe('features/popup-menu', function() { eventBus.on('popupMenu.open', openSpy); eventBus.on('popupMenu.opened', openedSpy); - // when popupMenu.open({}, 'menu', { x: 100, y: 100 }); @@ -1026,7 +1025,51 @@ describe('features/popup-menu', function() { afterEach(sinon.restore); - it('should close menu (contextPad.close)', inject(function(popupMenu, eventBus) { + it('should refresh (element.changed)',inject(function(eventBus, popupMenu) { + + // given + popupMenu.registerProvider('menu', menuProvider); + + const element = { id: 'foo' }; + + popupMenu.open(element, 'menu', { x: 100, y: 100 }); + + const refreshSpy = sinon.spy(); + + eventBus.on('popupMenu.refresh', refreshSpy); + + // when + eventBus.fire('element.changed', { + element + }); + + // then + expect(refreshSpy).to.have.been.calledOnce; + })); + + + it('should not refresh (element.changed)',inject(function(eventBus, popupMenu) { + + // given + popupMenu.registerProvider('menu', menuProvider); + + popupMenu.open({ id: 'foo' }, 'menu', { x: 100, y: 100 }); + + const refreshSpy = sinon.spy(); + + eventBus.on('popupMenu.refresh', refreshSpy); + + // when + eventBus.fire('element.changed', { + element: { id: 'bar' } + }); + + // then + expect(refreshSpy).not.to.have.been.called; + })); + + + it('should close (contextPad.close)', inject(function(popupMenu, eventBus) { // given popupMenu.registerProvider('menu', menuProvider); @@ -1043,7 +1086,7 @@ describe('features/popup-menu', function() { })); - it('should close menu (canvas.viewbox.changing)', inject(function(popupMenu, eventBus) { + it('should close (canvas.viewbox.changing)', inject(function(popupMenu, eventBus) { // given popupMenu.registerProvider('menu', menuProvider);