From b3c9389e740e75cd355003068d34c632719ab365 Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Thu, 19 Sep 2024 16:30:38 +0300 Subject: [PATCH 1/7] refactor: return reordered items and parent from event --- .../flow/component/dashboard/Dashboard.java | 61 +++--------- .../DashboardItemReorderEndEvent.java | 98 +++++++++++++++++-- 2 files changed, 103 insertions(+), 56 deletions(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java index fbb51ed726e..99a0ac1603a 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java @@ -11,10 +11,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -30,9 +28,6 @@ import com.vaadin.flow.dom.Element; import com.vaadin.flow.shared.Registration; -import elemental.json.JsonArray; -import elemental.json.JsonObject; - /** * @author Vaadin Ltd */ @@ -498,9 +493,8 @@ private void onItemReorderEnd( if (!isEditable()) { return; } - JsonArray orderedItemsFromClient = dashboardItemReorderEndEvent - .getItems(); - reorderItems(orderedItemsFromClient); + reorderItems(dashboardItemReorderEndEvent.getReorderedItemsParent(), + dashboardItemReorderEndEvent.getReorderedItems()); updateClient(); } @@ -523,48 +517,15 @@ private void onItemRemoved( dashboardItemRemovedEvent.getRemovedItem().removeFromParent(); } - private void reorderItems(JsonArray orderedItemsFromClient) { - // Keep references to the root level children before clearing them - Map nodeIdToComponent = childrenComponents.stream() - .collect(Collectors.toMap( - component -> component.getElement().getNode().getId(), - Function.identity())); - // Remove all children and add them back using the node IDs from client - // items - childrenComponents.clear(); - for (int rootLevelItemIdx = 0; rootLevelItemIdx < orderedItemsFromClient - .length(); rootLevelItemIdx++) { - JsonObject rootLevelItemFromClient = orderedItemsFromClient - .getObject(rootLevelItemIdx); - int rootLevelItemNodeId = (int) rootLevelItemFromClient - .getNumber("nodeid"); - Component componentMatch = nodeIdToComponent - .get(rootLevelItemNodeId); - childrenComponents.add(componentMatch); - // Reorder the widgets in sections separately - if (componentMatch instanceof DashboardSection sectionMatch) { - reorderSectionWidgets(sectionMatch, rootLevelItemFromClient); - } - } - } - - private void reorderSectionWidgets(DashboardSection section, - JsonObject rootLevelItem) { - // Keep references to the widgets before clearing them - Map nodeIdToWidget = section.getWidgets() - .stream() - .collect(Collectors.toMap( - widget -> widget.getElement().getNode().getId(), - Function.identity())); - // Remove all widgets and add them back using the node IDs from client - // items - section.removeAll(); - JsonArray sectionWidgetsFromClient = rootLevelItem.getArray("items"); - for (int sectionWidgetIdx = 0; sectionWidgetIdx < sectionWidgetsFromClient - .length(); sectionWidgetIdx++) { - int sectionItemNodeId = (int) sectionWidgetsFromClient - .getObject(sectionWidgetIdx).getNumber("nodeid"); - section.add(nodeIdToWidget.get(sectionItemNodeId)); + private void reorderItems(HasWidgets reorderedItemParent, + List items) { + if (reorderedItemParent instanceof DashboardSection parentSection) { + parentSection.removeAll(); + items.stream().map(DashboardWidget.class::cast) + .forEach(parentSection::add); + } else { + childrenComponents.clear(); + childrenComponents.addAll(items); } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java index 22ff4dbf79e..efd6d67281f 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java @@ -8,12 +8,20 @@ */ package com.vaadin.flow.component.dashboard; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.ComponentEvent; import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.DomEvent; import com.vaadin.flow.component.EventData; import elemental.json.JsonArray; +import elemental.json.JsonObject; /** * Widget or section reorder end event of {@link Dashboard}. @@ -24,7 +32,11 @@ @DomEvent("dashboard-item-reorder-end-flow") public class DashboardItemReorderEndEvent extends ComponentEvent { - private final JsonArray items; + private List reorderedItems; + + private JsonArray reorderedItemsFromClient; + + private HasWidgets reorderedItemsParent; /** * Creates a dashboard item reorder end event. @@ -34,19 +46,93 @@ public class DashboardItemReorderEndEvent extends ComponentEvent { * @param fromClient * true if the event originated from the client * side, false otherwise + * @param items + * The ordered items represented by node IDs as a + * {@link JsonArray} */ public DashboardItemReorderEndEvent(Dashboard source, boolean fromClient, @EventData("event.detail.items") JsonArray items) { super(source, fromClient); - this.items = items; + setReorderedItemParent(source, items); + setReorderedItems(); + } + + /** + * Returns the parent of the reordered items. Either a dashboard or a + * section. + * + * @return the parent of the reordered items + */ + public HasWidgets getReorderedItemsParent() { + return reorderedItemsParent; } /** - * Returns the ordered items from the client side + * Returns the list of the reordered item and its sibling items * - * @return items the ordered items as a {@link JsonArray} + * @return the list of the reordered item and its sibling items */ - public JsonArray getItems() { - return items; + public List getReorderedItems() { + return reorderedItems; + } + + private void setReorderedItemParent(Dashboard source, + JsonArray itemsFromClient) { + List serverItems = source.getChildren().toList(); + for (int rootLevelIdx = 0; rootLevelIdx < itemsFromClient + .length(); rootLevelIdx++) { + if (isNodeIdDifferentForIndex(itemsFromClient, serverItems, + rootLevelIdx)) { + this.reorderedItemsParent = source; + this.reorderedItemsFromClient = itemsFromClient; + return; + } + if (serverItems + .get(rootLevelIdx) instanceof DashboardSection section + && isSectionItemReordered(section, + itemsFromClient.get(rootLevelIdx))) { + this.reorderedItemsParent = section; + this.reorderedItemsFromClient = ((JsonObject) itemsFromClient + .get(rootLevelIdx)).getArray("items"); + return; + } + } + } + + private void setReorderedItems() { + Map nodeIdToItems = ((Component) reorderedItemsParent) + .getChildren() + .collect(Collectors.toMap( + item -> item.getElement().getNode().getId(), + Function.identity())); + List items = new ArrayList<>(); + for (int index = 0; index < reorderedItemsFromClient + .length(); index++) { + int nodeIdFromClient = (int) ((JsonObject) reorderedItemsFromClient + .get(index)).getNumber("nodeid"); + items.add(nodeIdToItems.get(nodeIdFromClient)); + } + this.reorderedItems = items; + } + + private static boolean isSectionItemReordered(DashboardSection section, + JsonObject itemFromClient) { + List sectionItems = section.getChildren().toList(); + JsonArray clientSectionItems = itemFromClient.getArray("items"); + for (int index = 0; index < clientSectionItems.length(); index++) { + if (isNodeIdDifferentForIndex(clientSectionItems, sectionItems, + index)) { + return true; + } + } + return false; + } + + private static boolean isNodeIdDifferentForIndex(JsonArray clientItems, + List items, int index) { + JsonObject itemFromClient = clientItems.get(index); + int nodeIdFromClient = (int) itemFromClient.getNumber("nodeid"); + int nodeIdFromServer = items.get(index).getElement().getNode().getId(); + return nodeIdFromClient != nodeIdFromServer; } } From 6040886d421c45cbe840dcd687a701a3821b7bd3 Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Fri, 20 Sep 2024 10:03:14 +0300 Subject: [PATCH 2/7] fix: handle the case where drag reorder returns the same items --- .../dashboard/DashboardItemReorderEndEvent.java | 8 +++++++- .../dashboard/tests/DashboardDragReorderTest.java | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java index efd6d67281f..7ff88f20ef5 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java @@ -54,7 +54,13 @@ public DashboardItemReorderEndEvent(Dashboard source, boolean fromClient, @EventData("event.detail.items") JsonArray items) { super(source, fromClient); setReorderedItemParent(source, items); - setReorderedItems(); + if (reorderedItemsParent == null) { + // No reordering + reorderedItemsParent = source; + reorderedItems = source.getChildren().toList(); + } else { + setReorderedItems(); + } } /** diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java index bdddead6019..cc278f8d734 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java @@ -50,6 +50,11 @@ public void reorderWidget_orderIsUpdated() { assertRootLevelItemReorder(0, 1); } + @Test + public void reorderWidgetToSamePosition_orderIsNotUpdated() { + assertRootLevelItemReorder(0, 0); + } + @Test public void reorderSection_orderIsUpdated() { assertRootLevelItemReorder(2, 1); @@ -60,6 +65,11 @@ public void reorderWidgetInSection_orderIsUpdated() { assertSectionWidgetReorder(2, 0, 1); } + @Test + public void reorderWidgetInSectionToSamePosition_orderIsNotUpdated() { + assertSectionWidgetReorder(2, 0, 0); + } + @Test public void setDashboardNotEditable_reorderWidget_orderIsNotUpdated() { dashboard.setEditable(false); From 65499829d433f4de13cbd9922c9f0ce2b18cf8cb Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Fri, 20 Sep 2024 10:03:35 +0300 Subject: [PATCH 3/7] chore: remove unused code --- .../component/dashboard/tests/DashboardDragReorderIT.java | 4 ---- .../component/dashboard/tests/DashboardDragResizeIT.java | 6 ------ 2 files changed, 10 deletions(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java index fb5cdc82a6b..c22ae08e003 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java @@ -83,10 +83,6 @@ private void dragResizeElement(TestBenchElement draggedElement, .release(targetElement).build().perform(); } - private static boolean isDragHandleVisible(TestBenchElement element) { - return !"none".equals(getDragHandle(element).getCssValue("display")); - } - private static TestBenchElement getDragHandle(TestBenchElement element) { return element.$("*").withClassName("drag-handle").first(); } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeIT.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeIT.java index 371b641d566..32698305e27 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeIT.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeIT.java @@ -81,12 +81,6 @@ private void resizeWidget(int widgetIndexToResize, double xResizeRatio, .release().build().perform(); } - private boolean isResizeHandleVisible( - DashboardWidgetElement widgetElement) { - return !"none" - .equals(getResizeHandle(widgetElement).getCssValue("display")); - } - private static TestBenchElement getResizeHandle( DashboardWidgetElement widgetElement) { return widgetElement.$("*").withClassName("resize-handle").first(); From 1731de251039d06ac935644e8d3bcbcf7ee2800f Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Fri, 20 Sep 2024 10:06:28 +0300 Subject: [PATCH 4/7] chore: rename incorrectly named test method --- .../component/dashboard/tests/DashboardDragReorderIT.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java index c22ae08e003..ac316882bb5 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow-integration-tests/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderIT.java @@ -36,7 +36,7 @@ public void init() { public void reorderWidgetOnClientSide_itemsAreReorderedCorrectly() { var draggedWidget = dashboardElement.getWidgets().get(0); var targetWidget = dashboardElement.getWidgets().get(1); - dragResizeElement(draggedWidget, targetWidget); + dragReorderElement(draggedWidget, targetWidget); Assert.assertEquals(draggedWidget.getTitle(), dashboardElement.getWidgets().get(1).getTitle()); } @@ -45,7 +45,7 @@ public void reorderWidgetOnClientSide_itemsAreReorderedCorrectly() { public void reorderSectionOnClientSide_itemsAreReorderedCorrectly() { var draggedSection = dashboardElement.getSections().get(1); var targetWidget = dashboardElement.getWidgets().get(0); - dragResizeElement(draggedSection, targetWidget); + dragReorderElement(draggedSection, targetWidget); Assert.assertEquals(draggedSection.getTitle(), dashboardElement.getSections().get(0).getTitle()); } @@ -55,7 +55,7 @@ public void reorderWidgetInSectionOnClientSide_itemsAreReorderedCorrectly() { var firstSection = dashboardElement.getSections().get(0); var draggedWidget = firstSection.getWidgets().get(0); var targetWidget = firstSection.getWidgets().get(1); - dragResizeElement(draggedWidget, targetWidget); + dragReorderElement(draggedWidget, targetWidget); firstSection = dashboardElement.getSections().get(0); Assert.assertEquals(draggedWidget.getTitle(), firstSection.getWidgets().get(1).getTitle()); @@ -69,7 +69,7 @@ public void detachReattach_reorderWidgetOnClientSide_itemsAreReorderedCorrectly( reorderWidgetOnClientSide_itemsAreReorderedCorrectly(); } - private void dragResizeElement(TestBenchElement draggedElement, + private void dragReorderElement(TestBenchElement draggedElement, TestBenchElement targetElement) { var dragHandle = getDragHandle(draggedElement); From fd8c3b60b2de4eb2ae75bf827b6825994fbc5138 Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Fri, 20 Sep 2024 14:16:19 +0300 Subject: [PATCH 5/7] refactor: update events based on web component event changes --- .../flow/component/dashboard/Dashboard.java | 75 +++------ .../dashboard/DashboardItemMovedEvent.java | 119 +++++++++++++++ .../DashboardItemReorderEndEvent.java | 144 ------------------ .../DashboardItemReorderStartEvent.java | 37 ----- .../DashboardItemResizeStartEvent.java | 54 ------- ...nt.java => DashboardItemResizedEvent.java} | 14 +- .../tests/DashboardDragReorderTest.java | 20 ++- .../tests/DashboardDragResizeTest.java | 14 +- 8 files changed, 171 insertions(+), 306 deletions(-) create mode 100644 vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java delete mode 100644 vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java delete mode 100644 vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderStartEvent.java delete mode 100644 vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeStartEvent.java rename vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/{DashboardItemResizeEndEvent.java => DashboardItemResizedEvent.java} (82%) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java index 99a0ac1603a..afbc3d0db10 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java @@ -50,8 +50,8 @@ public class Dashboard extends Component implements HasWidgets, HasSize { */ public Dashboard() { childDetachHandler = getChildDetachHandler(); - addItemReorderEndListener(this::onItemReorderEnd); - addItemResizeEndListener(this::onItemResizeEnd); + addItemMovedListener(this::onItemMoved); + addItemResizedListener(this::onItemResized); addItemRemovedListener(this::onItemRemoved); } @@ -300,51 +300,27 @@ public boolean isEditable() { } /** - * Adds an item reorder start listener to this dashboard. + * Adds an item moved listener to this dashboard. * * @param listener * the listener to add, not null * @return a handle that can be used for removing the listener */ - public Registration addItemReorderStartListener( - ComponentEventListener listener) { - return addListener(DashboardItemReorderStartEvent.class, listener); + public Registration addItemMovedListener( + ComponentEventListener listener) { + return addListener(DashboardItemMovedEvent.class, listener); } /** - * Adds an item reorder end listener to this dashboard. + * Adds an item resized listener to this dashboard. * * @param listener * the listener to add, not null * @return a handle that can be used for removing the listener */ - public Registration addItemReorderEndListener( - ComponentEventListener listener) { - return addListener(DashboardItemReorderEndEvent.class, listener); - } - - /** - * Adds an item resize start listener to this dashboard. - * - * @param listener - * the listener to add, not null - * @return a handle that can be used for removing the listener - */ - public Registration addItemResizeStartListener( - ComponentEventListener listener) { - return addListener(DashboardItemResizeStartEvent.class, listener); - } - - /** - * Adds an item resize end listener to this dashboard. - * - * @param listener - * the listener to add, not null - * @return a handle that can be used for removing the listener - */ - public Registration addItemResizeEndListener( - ComponentEventListener listener) { - return addListener(DashboardItemResizeEndEvent.class, listener); + public Registration addItemResizedListener( + ComponentEventListener listener) { + return addListener(DashboardItemResizedEvent.class, listener); } /** @@ -384,7 +360,7 @@ protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); getElement().executeJs( "Vaadin.FlowComponentHost.patchVirtualContainer(this);"); - customizeItemReorderEndEvent(); + customizeItemMovedEvent(); doUpdateClient(); } @@ -488,25 +464,24 @@ void removeChild(Component child) { }; } - private void onItemReorderEnd( - DashboardItemReorderEndEvent dashboardItemReorderEndEvent) { + private void onItemMoved(DashboardItemMovedEvent dashboardItemMovedEvent) { if (!isEditable()) { return; } - reorderItems(dashboardItemReorderEndEvent.getReorderedItemsParent(), - dashboardItemReorderEndEvent.getReorderedItems()); + reorderItems(dashboardItemMovedEvent.getReorderedItemsParent(), + dashboardItemMovedEvent.getReorderedItems()); updateClient(); } - private void onItemResizeEnd( - DashboardItemResizeEndEvent dashboardItemResizeEndEvent) { + private void onItemResized( + DashboardItemResizedEvent dashboardItemResizedEvent) { if (!isEditable()) { return; } - DashboardWidget resizedWidget = dashboardItemResizeEndEvent + DashboardWidget resizedWidget = dashboardItemResizedEvent .getResizedWidget(); - resizedWidget.setRowspan(dashboardItemResizeEndEvent.getRowspan()); - resizedWidget.setColspan(dashboardItemResizeEndEvent.getColspan()); + resizedWidget.setRowspan(dashboardItemResizedEvent.getRowspan()); + resizedWidget.setColspan(dashboardItemResizedEvent.getColspan()); } private void onItemRemoved( @@ -517,7 +492,7 @@ private void onItemRemoved( dashboardItemRemovedEvent.getRemovedItem().removeFromParent(); } - private void reorderItems(HasWidgets reorderedItemParent, + private void reorderItems(Component reorderedItemParent, List items) { if (reorderedItemParent instanceof DashboardSection parentSection) { parentSection.removeAll(); @@ -529,20 +504,20 @@ private void reorderItems(HasWidgets reorderedItemParent, } } - private void customizeItemReorderEndEvent() { + private void customizeItemMovedEvent() { getElement().executeJs( """ - this.addEventListener('dashboard-item-reorder-end', (e) => { + this.addEventListener('dashboard-item-moved', (e) => { function mapItems(items) { return items.map(({nodeid, items}) => ({ nodeid, ...(items && { items: mapItems(items) }) })); } - const flowReorderEvent = new CustomEvent('dashboard-item-reorder-end-flow', { - detail: { items: mapItems(this.items) } + const flowItemMovedEvent = new CustomEvent('dashboard-item-moved-flow', { + detail: { items: mapItems(e.detail.items), section: e.detail.section?.nodeid } }); - this.dispatchEvent(flowReorderEvent); + this.dispatchEvent(flowItemMovedEvent); });"""); } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java new file mode 100644 index 00000000000..dfef40aea87 --- /dev/null +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java @@ -0,0 +1,119 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.dashboard; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; + +import elemental.json.JsonArray; +import elemental.json.JsonObject; + +/** + * Widget or section moved event of {@link Dashboard}. + * + * @author Vaadin Ltd. + * @see Dashboard#addItemMovedListener(ComponentEventListener) + */ +@DomEvent("dashboard-item-moved-flow") +public class DashboardItemMovedEvent extends ComponentEvent { + + private final List reorderedItems; + + private final Component reorderedItemsParent; + + /** + * Creates a dashboard item moved event. + * + * @param source + * Dashboard that contains the item that was moved + * @param fromClient + * true if the event originated from the client + * side, false otherwise + * @param items + * The ordered items represented by node IDs as a + * {@link JsonArray} + */ + public DashboardItemMovedEvent(Dashboard source, boolean fromClient, + @EventData("event.detail.items") JsonArray items, + @EventData("event.detail.section") Integer sectionNodeId) { + super(source, fromClient); + if (sectionNodeId == null) { + reorderedItemsParent = source; + reorderedItems = getReorderedItemsList(items); + } else { + reorderedItemsParent = source.getChildren() + .filter(child -> sectionNodeId + .equals(child.getElement().getNode().getId())) + .map(DashboardSection.class::cast).findAny().orElseThrow(); + reorderedItems = getReorderedItemsList( + getSectionItems(items, sectionNodeId)); + } + } + + /** + * Returns the parent of the reordered items. Either a dashboard or a + * section. + * + * @return the parent of the reordered items + */ + public Component getReorderedItemsParent() { + return reorderedItemsParent; + } + + /** + * Returns the list of the reordered item and its sibling items + * + * @return the list of the reordered item and its sibling items + */ + public List getReorderedItems() { + return reorderedItems; + } + + private List getReorderedItemsList( + JsonArray reorderedItemsFromClient) { + Objects.requireNonNull(reorderedItemsFromClient); + Map nodeIdToItems = reorderedItemsParent + .getChildren() + .collect(Collectors.toMap( + item -> item.getElement().getNode().getId(), + Function.identity())); + List items = new ArrayList<>(); + for (int index = 0; index < reorderedItemsFromClient + .length(); index++) { + int nodeIdFromClient = (int) ((JsonObject) reorderedItemsFromClient + .get(index)).getNumber("nodeid"); + items.add(nodeIdToItems.get(nodeIdFromClient)); + } + return items; + } + + private static JsonArray getSectionItems(JsonArray items, + int sectionNodeId) { + for (int rootLevelIdx = 0; rootLevelIdx < items + .length(); rootLevelIdx++) { + JsonObject item = items.get(rootLevelIdx); + int itemNodeId = (int) item.getNumber("nodeid"); + if (sectionNodeId == itemNodeId) { + JsonObject sectionObj = items.get(rootLevelIdx); + return sectionObj.getArray("items"); + } + } + return null; + } +} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java deleted file mode 100644 index 7ff88f20ef5..00000000000 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderEndEvent.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2000-2024 Vaadin Ltd. - * - * This program is available under Vaadin Commercial License and Service Terms. - * - * See {@literal } for the full - * license. - */ -package com.vaadin.flow.component.dashboard; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; -import com.vaadin.flow.component.EventData; - -import elemental.json.JsonArray; -import elemental.json.JsonObject; - -/** - * Widget or section reorder end event of {@link Dashboard}. - * - * @author Vaadin Ltd. - * @see Dashboard#addItemReorderEndListener(ComponentEventListener) - */ -@DomEvent("dashboard-item-reorder-end-flow") -public class DashboardItemReorderEndEvent extends ComponentEvent { - - private List reorderedItems; - - private JsonArray reorderedItemsFromClient; - - private HasWidgets reorderedItemsParent; - - /** - * Creates a dashboard item reorder end event. - * - * @param source - * Dashboard that contains the item that was dragged - * @param fromClient - * true if the event originated from the client - * side, false otherwise - * @param items - * The ordered items represented by node IDs as a - * {@link JsonArray} - */ - public DashboardItemReorderEndEvent(Dashboard source, boolean fromClient, - @EventData("event.detail.items") JsonArray items) { - super(source, fromClient); - setReorderedItemParent(source, items); - if (reorderedItemsParent == null) { - // No reordering - reorderedItemsParent = source; - reorderedItems = source.getChildren().toList(); - } else { - setReorderedItems(); - } - } - - /** - * Returns the parent of the reordered items. Either a dashboard or a - * section. - * - * @return the parent of the reordered items - */ - public HasWidgets getReorderedItemsParent() { - return reorderedItemsParent; - } - - /** - * Returns the list of the reordered item and its sibling items - * - * @return the list of the reordered item and its sibling items - */ - public List getReorderedItems() { - return reorderedItems; - } - - private void setReorderedItemParent(Dashboard source, - JsonArray itemsFromClient) { - List serverItems = source.getChildren().toList(); - for (int rootLevelIdx = 0; rootLevelIdx < itemsFromClient - .length(); rootLevelIdx++) { - if (isNodeIdDifferentForIndex(itemsFromClient, serverItems, - rootLevelIdx)) { - this.reorderedItemsParent = source; - this.reorderedItemsFromClient = itemsFromClient; - return; - } - if (serverItems - .get(rootLevelIdx) instanceof DashboardSection section - && isSectionItemReordered(section, - itemsFromClient.get(rootLevelIdx))) { - this.reorderedItemsParent = section; - this.reorderedItemsFromClient = ((JsonObject) itemsFromClient - .get(rootLevelIdx)).getArray("items"); - return; - } - } - } - - private void setReorderedItems() { - Map nodeIdToItems = ((Component) reorderedItemsParent) - .getChildren() - .collect(Collectors.toMap( - item -> item.getElement().getNode().getId(), - Function.identity())); - List items = new ArrayList<>(); - for (int index = 0; index < reorderedItemsFromClient - .length(); index++) { - int nodeIdFromClient = (int) ((JsonObject) reorderedItemsFromClient - .get(index)).getNumber("nodeid"); - items.add(nodeIdToItems.get(nodeIdFromClient)); - } - this.reorderedItems = items; - } - - private static boolean isSectionItemReordered(DashboardSection section, - JsonObject itemFromClient) { - List sectionItems = section.getChildren().toList(); - JsonArray clientSectionItems = itemFromClient.getArray("items"); - for (int index = 0; index < clientSectionItems.length(); index++) { - if (isNodeIdDifferentForIndex(clientSectionItems, sectionItems, - index)) { - return true; - } - } - return false; - } - - private static boolean isNodeIdDifferentForIndex(JsonArray clientItems, - List items, int index) { - JsonObject itemFromClient = clientItems.get(index); - int nodeIdFromClient = (int) itemFromClient.getNumber("nodeid"); - int nodeIdFromServer = items.get(index).getElement().getNode().getId(); - return nodeIdFromClient != nodeIdFromServer; - } -} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderStartEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderStartEvent.java deleted file mode 100644 index d2910539cfb..00000000000 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemReorderStartEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2000-2024 Vaadin Ltd. - * - * This program is available under Vaadin Commercial License and Service Terms. - * - * See {@literal } for the full - * license. - */ -package com.vaadin.flow.component.dashboard; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; - -/** - * Widget or section reorder start event of {@link Dashboard}. - * - * @author Vaadin Ltd. - * @see Dashboard#addItemReorderStartListener(ComponentEventListener) - */ -@DomEvent("dashboard-item-reorder-start") -public class DashboardItemReorderStartEvent extends ComponentEvent { - - /** - * Creates a dashboard item reorder start event. - * - * @param source - * Dashboard that contains the item that was dragged - * @param fromClient - * true if the event originated from the client - * side, false otherwise - */ - public DashboardItemReorderStartEvent(Dashboard source, - boolean fromClient) { - super(source, fromClient); - } -} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeStartEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeStartEvent.java deleted file mode 100644 index ce762351439..00000000000 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeStartEvent.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2000-2024 Vaadin Ltd. - * - * This program is available under Vaadin Commercial License and Service Terms. - * - * See {@literal } for the full - * license. - */ -package com.vaadin.flow.component.dashboard; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; -import com.vaadin.flow.component.EventData; - -/** - * Widget resize start event of {@link Dashboard}. - * - * @author Vaadin Ltd. - * @see Dashboard#addItemResizeStartListener(ComponentEventListener) - */ -@DomEvent("dashboard-item-resize-start") -public class DashboardItemResizeStartEvent extends ComponentEvent { - - private final DashboardWidget resizedWidget; - - /** - * Creates a dashboard item resize start event. - * - * @param source - * Dashboard that contains the widget that was dragged - * @param fromClient - * true if the event originated from the client - * side, false otherwise - * @param nodeId - * Node ID the resized widget - */ - public DashboardItemResizeStartEvent(Dashboard source, boolean fromClient, - @EventData("event.detail.item.nodeid") int nodeId) { - super(source, fromClient); - this.resizedWidget = source.getWidgets().stream() - .filter(child -> nodeId == child.getElement().getNode().getId()) - .findAny().orElse(null); - } - - /** - * Returns the resized widget - * - * @return the resized widget - */ - public DashboardWidget getResizedWidget() { - return resizedWidget; - } -} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeEndEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java similarity index 82% rename from vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeEndEvent.java rename to vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java index 013ec38963c..0d66ee06a57 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeEndEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java @@ -14,13 +14,13 @@ import com.vaadin.flow.component.EventData; /** - * Widget resize end event of {@link Dashboard}. + * Widget resized event of {@link Dashboard}. * * @author Vaadin Ltd. - * @see Dashboard#addItemResizeEndListener(ComponentEventListener) + * @see Dashboard#addItemResizedListener(ComponentEventListener) */ -@DomEvent("dashboard-item-resize-end") -public class DashboardItemResizeEndEvent extends ComponentEvent { +@DomEvent("dashboard-item-resized") +public class DashboardItemResizedEvent extends ComponentEvent { private final DashboardWidget resizedWidget; @@ -29,10 +29,10 @@ public class DashboardItemResizeEndEvent extends ComponentEvent { private final int rowspan; /** - * Creates a dashboard item resize end event. + * Creates a dashboard item resized event. * * @param source - * Dashboard that contains the widget that was dragged + * Dashboard that contains the widget that was resized * @param fromClient * true if the event originated from the client * side, false otherwise @@ -43,7 +43,7 @@ public class DashboardItemResizeEndEvent extends ComponentEvent { * @param rowspan * New rowspan of the resized widget */ - public DashboardItemResizeEndEvent(Dashboard source, boolean fromClient, + public DashboardItemResizedEvent(Dashboard source, boolean fromClient, @EventData("event.detail.item.nodeid") int nodeId, @EventData("event.detail.item.colspan") int colspan, @EventData("event.detail.item.rowspan") int rowspan) { diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java index cc278f8d734..0adf255ed5d 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java @@ -18,7 +18,7 @@ import com.vaadin.flow.component.ComponentUtil; import com.vaadin.flow.component.dashboard.Dashboard; -import com.vaadin.flow.component.dashboard.DashboardItemReorderEndEvent; +import com.vaadin.flow.component.dashboard.DashboardItemMovedEvent; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; @@ -75,13 +75,17 @@ public void setDashboardNotEditable_reorderWidget_orderIsNotUpdated() { dashboard.setEditable(false); List expectedRootLevelNodeIds = getRootLevelNodeIds(); reorderRootLevelItem(0, 1); - fireItemReorderEndEvent(); + fireItemMovedEvent(); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } - private void fireItemReorderEndEvent() { - ComponentUtil.fireEvent(dashboard, - new DashboardItemReorderEndEvent(dashboard, false, itemsArray)); + private void fireItemMovedEvent() { + fireItemMovedEvent(null); + } + + private void fireItemMovedEvent(Integer sectionNodeId) { + ComponentUtil.fireEvent(dashboard, new DashboardItemMovedEvent( + dashboard, false, itemsArray, sectionNodeId)); } private List getSectionWidgetNodeIds(int sectionIndex) { @@ -132,10 +136,12 @@ private void reorderRootLevelItem(int initialIndex, int finalIndex) { private void assertSectionWidgetReorder(int sectionIndex, int initialIndex, int finalIndex) { + int sectionNodeId = dashboard.getChildren().toList().get(sectionIndex) + .getElement().getNode().getId(); reorderSectionWidget(sectionIndex, initialIndex, finalIndex); List expectedSectionWidgetNodeIds = getExpectedSectionWidgetNodeIds( sectionIndex, initialIndex, finalIndex); - fireItemReorderEndEvent(); + fireItemMovedEvent(sectionNodeId); Assert.assertEquals(expectedSectionWidgetNodeIds, getSectionWidgetNodeIds(sectionIndex)); } @@ -144,7 +150,7 @@ private void assertRootLevelItemReorder(int initialIndex, int finalIndex) { reorderRootLevelItem(initialIndex, finalIndex); List expectedRootLevelNodeIds = getExpectedRootLevelItemNodeIds( initialIndex, finalIndex); - fireItemReorderEndEvent(); + fireItemMovedEvent(); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java index 8a901a0f961..5345f7947d3 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java @@ -14,7 +14,7 @@ import com.vaadin.flow.component.ComponentUtil; import com.vaadin.flow.component.dashboard.Dashboard; -import com.vaadin.flow.component.dashboard.DashboardItemResizeEndEvent; +import com.vaadin.flow.component.dashboard.DashboardItemResizedEvent; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; @@ -68,7 +68,7 @@ public void resizeWidgetInSectionBothHorizontallyAndVertically_sizeIsUpdated() { public void setDashboardNotEditable_resizeWidget_sizeIsNotUpdated() { dashboard.setEditable(false); DashboardWidget widgetToResize = dashboard.getWidgets().get(0); - fireItemResizeEndEvent(widgetToResize, 2, 2); + fireItemResizedEvent(widgetToResize, 2, 2); Assert.assertEquals(1, widgetToResize.getColspan()); Assert.assertEquals(1, widgetToResize.getRowspan()); } @@ -78,19 +78,19 @@ private void assertWidgetResized(int widgetIndexToResize, int targetColspan, DashboardWidget widgetToResize = dashboard.getWidgets() .get(widgetIndexToResize); // Assert widget is enlarged - fireItemResizeEndEvent(widgetToResize, targetColspan, targetRowspan); + fireItemResizedEvent(widgetToResize, targetColspan, targetRowspan); Assert.assertEquals(targetColspan, widgetToResize.getColspan()); Assert.assertEquals(targetRowspan, widgetToResize.getRowspan()); // Assert widget is shrunk - fireItemResizeEndEvent(widgetToResize, 1, 1); + fireItemResizedEvent(widgetToResize, 1, 1); Assert.assertEquals(1, widgetToResize.getColspan()); Assert.assertEquals(1, widgetToResize.getRowspan()); } - private void fireItemResizeEndEvent(DashboardWidget widget, - int targetColspan, int targetRowspan) { + private void fireItemResizedEvent(DashboardWidget widget, int targetColspan, + int targetRowspan) { ComponentUtil.fireEvent(dashboard, - new DashboardItemResizeEndEvent(dashboard, false, + new DashboardItemResizedEvent(dashboard, false, widget.getElement().getNode().getId(), targetColspan, targetRowspan)); } From e2c67f08153f0f59b4247db183d8ac44cbd7cfaa Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Mon, 23 Sep 2024 18:55:39 +0300 Subject: [PATCH 6/7] refactor: align event apis with web component --- .../flow/component/dashboard/Dashboard.java | 193 ++++++++++++++---- .../dashboard/DashboardItemMovedEvent.java | 101 +++------ .../dashboard/DashboardItemRemovedEvent.java | 46 ++--- .../dashboard/DashboardItemResizedEvent.java | 58 ++---- .../tests/DashboardDragReorderTest.java | 136 +++++++++++- .../tests/DashboardDragResizeTest.java | 72 ++++++- .../dashboard/tests/DashboardTest.java | 91 ++++++++- 7 files changed, 506 insertions(+), 191 deletions(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java index afbc3d0db10..d13a30bc5bd 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java @@ -11,8 +11,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -25,9 +27,14 @@ import com.vaadin.flow.component.Tag; import com.vaadin.flow.component.dependency.JsModule; import com.vaadin.flow.component.dependency.NpmPackage; +import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.dom.DomListenerRegistration; import com.vaadin.flow.dom.Element; import com.vaadin.flow.shared.Registration; +import elemental.json.JsonArray; +import elemental.json.JsonObject; + /** * @author Vaadin Ltd */ @@ -50,9 +57,9 @@ public class Dashboard extends Component implements HasWidgets, HasSize { */ public Dashboard() { childDetachHandler = getChildDetachHandler(); - addItemMovedListener(this::onItemMoved); - addItemResizedListener(this::onItemResized); - addItemRemovedListener(this::onItemRemoved); + initItemMovedClientEventListener(); + initItemResizedClientEventListener(); + initItemRemovedClientEventListener(); } /** @@ -464,44 +471,113 @@ void removeChild(Component child) { }; } - private void onItemMoved(DashboardItemMovedEvent dashboardItemMovedEvent) { - if (!isEditable()) { - return; - } - reorderItems(dashboardItemMovedEvent.getReorderedItemsParent(), - dashboardItemMovedEvent.getReorderedItems()); - updateClient(); - } - - private void onItemResized( - DashboardItemResizedEvent dashboardItemResizedEvent) { - if (!isEditable()) { - return; - } - DashboardWidget resizedWidget = dashboardItemResizedEvent - .getResizedWidget(); - resizedWidget.setRowspan(dashboardItemResizedEvent.getRowspan()); - resizedWidget.setColspan(dashboardItemResizedEvent.getColspan()); - } - - private void onItemRemoved( - DashboardItemRemovedEvent dashboardItemRemovedEvent) { - if (!isEditable()) { - return; - } - dashboardItemRemovedEvent.getRemovedItem().removeFromParent(); - } - - private void reorderItems(Component reorderedItemParent, - List items) { - if (reorderedItemParent instanceof DashboardSection parentSection) { - parentSection.removeAll(); - items.stream().map(DashboardWidget.class::cast) - .forEach(parentSection::add); - } else { + private void initItemMovedClientEventListener() { + String itemKey = "event.detail.item"; + String itemsKey = "event.detail.items"; + String sectionKey = "event.detail.section"; + getElement().addEventListener("dashboard-item-moved-flow", e -> { + if (!isEditable()) { + return; + } + handleItemMovedClientEvent(e, itemKey, itemsKey, sectionKey); + updateClient(); + }).addEventData(itemKey).addEventData(itemsKey) + .addEventData(sectionKey); + } + + private void handleItemMovedClientEvent(DomEvent e, String itemKey, + String itemsKey, String sectionKey) { + int itemNodeId = (int) e.getEventData().getNumber(itemKey); + JsonArray itemsNodeIds = e.getEventData().getArray(itemsKey); + Integer sectionNodeId = e.getEventData().hasKey(sectionKey) + ? (int) e.getEventData().getNumber(sectionKey) + : null; + DashboardSection section = null; + List reorderedItems; + if (sectionNodeId == null) { + reorderedItems = getReorderedItemsList(itemsNodeIds, this); childrenComponents.clear(); - childrenComponents.addAll(items); + childrenComponents.addAll(reorderedItems); + } else { + section = getChildren() + .filter(child -> sectionNodeId + .equals(child.getElement().getNode().getId())) + .map(DashboardSection.class::cast).findAny().orElseThrow(); + reorderedItems = getReorderedItemsList( + getSectionItems(itemsNodeIds, sectionNodeId), section); + section.removeAll(); + reorderedItems.stream().map(DashboardWidget.class::cast) + .forEach(section::add); } + Component movedItem = reorderedItems.stream().filter( + item -> itemNodeId == item.getElement().getNode().getId()) + .findAny().orElseThrow(); + fireEvent(new DashboardItemMovedEvent(this, true, movedItem, + getChildren().toList(), section)); + } + + private void initItemResizedClientEventListener() { + String nodeIdKey = "event.detail.item.nodeid"; + String colspanKey = "event.detail.item.colspan"; + String rowspanKey = "event.detail.item.rowspan"; + getElement().addEventListener("dashboard-item-resized", e -> { + if (!isEditable()) { + return; + } + handleItemResizedClientEvent(e, nodeIdKey, colspanKey, rowspanKey); + updateClient(); + }).addEventData(nodeIdKey).addEventData(colspanKey) + .addEventData(rowspanKey); + } + + private void handleItemResizedClientEvent(DomEvent e, String nodeIdKey, + String colspanKey, String rowspanKey) { + int nodeId = (int) e.getEventData().getNumber(nodeIdKey); + int colspan = (int) e.getEventData().getNumber(colspanKey); + int rowspan = (int) e.getEventData().getNumber(rowspanKey); + DashboardWidget resizedWidget = getWidgets().stream() + .filter(child -> nodeId == child.getElement().getNode().getId()) + .findAny().orElseThrow(); + resizedWidget.setRowspan(rowspan); + resizedWidget.setColspan(colspan); + fireEvent(new DashboardItemResizedEvent(this, true, resizedWidget, + getChildren().toList())); + } + + private void initItemRemovedClientEventListener() { + String nodeIdKey = "event.detail.item.nodeid"; + DomListenerRegistration registration = getElement() + .addEventListener("dashboard-item-removed", e -> { + if (!isEditable()) { + return; + } + handleItemRemovedClientEvent(e, nodeIdKey); + updateClient(); + }); + registration.addEventData(nodeIdKey); + } + + private void handleItemRemovedClientEvent(DomEvent e, String nodeIdKey) { + int nodeId = (int) e.getEventData().getNumber(nodeIdKey); + Component removedItem = getRemovedItem(nodeId); + removedItem.removeFromParent(); + fireEvent(new DashboardItemRemovedEvent(this, true, removedItem, + getChildren().toList())); + } + + private Component getRemovedItem(int nodeId) { + return getChildren().map(item -> { + if (nodeId == item.getElement().getNode().getId()) { + return item; + } + if (item instanceof DashboardSection section) { + return section.getWidgets().stream() + .filter(sectionItem -> nodeId == sectionItem + .getElement().getNode().getId()) + .findAny().orElse(null); + } + return null; + }).filter(Objects::nonNull).findAny().orElseThrow(); } private void customizeItemMovedEvent() { @@ -515,9 +591,46 @@ function mapItems(items) { })); } const flowItemMovedEvent = new CustomEvent('dashboard-item-moved-flow', { - detail: { items: mapItems(e.detail.items), section: e.detail.section?.nodeid } + detail: { + item: e.detail.item.nodeid, + items: mapItems(e.detail.items), + section: e.detail.section?.nodeid + } }); this.dispatchEvent(flowItemMovedEvent); });"""); } + + private static List getReorderedItemsList( + JsonArray reorderedItemsFromClient, + Component reorderedItemsParent) { + Objects.requireNonNull(reorderedItemsFromClient); + Map nodeIdToItems = reorderedItemsParent + .getChildren() + .collect(Collectors.toMap( + item -> item.getElement().getNode().getId(), + Function.identity())); + List items = new ArrayList<>(); + for (int index = 0; index < reorderedItemsFromClient + .length(); index++) { + int nodeIdFromClient = (int) ((JsonObject) reorderedItemsFromClient + .get(index)).getNumber("nodeid"); + items.add(nodeIdToItems.get(nodeIdFromClient)); + } + return items; + } + + private static JsonArray getSectionItems(JsonArray items, + int sectionNodeId) { + for (int rootLevelIdx = 0; rootLevelIdx < items + .length(); rootLevelIdx++) { + JsonObject item = items.get(rootLevelIdx); + int itemNodeId = (int) item.getNumber("nodeid"); + if (sectionNodeId == itemNodeId) { + JsonObject sectionObj = items.get(rootLevelIdx); + return sectionObj.getArray("items"); + } + } + return null; + } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java index dfef40aea87..4bc081bffea 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMovedEvent.java @@ -8,21 +8,12 @@ */ package com.vaadin.flow.component.dashboard; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.Optional; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.ComponentEvent; import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; -import com.vaadin.flow.component.EventData; - -import elemental.json.JsonArray; -import elemental.json.JsonObject; /** * Widget or section moved event of {@link Dashboard}. @@ -30,12 +21,13 @@ * @author Vaadin Ltd. * @see Dashboard#addItemMovedListener(ComponentEventListener) */ -@DomEvent("dashboard-item-moved-flow") public class DashboardItemMovedEvent extends ComponentEvent { - private final List reorderedItems; + private final Component item; + + private final List items; - private final Component reorderedItemsParent; + private final DashboardSection section; /** * Creates a dashboard item moved event. @@ -43,77 +35,50 @@ public class DashboardItemMovedEvent extends ComponentEvent { * @param source * Dashboard that contains the item that was moved * @param fromClient - * true if the event originated from the client - * side, false otherwise + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param item + * The moved item * @param items - * The ordered items represented by node IDs as a - * {@link JsonArray} + * The root level items of the dashboard + * @param section + * The section that contains the moved item, {@code null} if the + * item is a direct child of the dashboard */ public DashboardItemMovedEvent(Dashboard source, boolean fromClient, - @EventData("event.detail.items") JsonArray items, - @EventData("event.detail.section") Integer sectionNodeId) { + Component item, List items, DashboardSection section) { super(source, fromClient); - if (sectionNodeId == null) { - reorderedItemsParent = source; - reorderedItems = getReorderedItemsList(items); - } else { - reorderedItemsParent = source.getChildren() - .filter(child -> sectionNodeId - .equals(child.getElement().getNode().getId())) - .map(DashboardSection.class::cast).findAny().orElseThrow(); - reorderedItems = getReorderedItemsList( - getSectionItems(items, sectionNodeId)); - } + this.item = item; + this.items = items; + this.section = section; } /** - * Returns the parent of the reordered items. Either a dashboard or a - * section. + * Returns the moved item * - * @return the parent of the reordered items + * @return the moved item */ - public Component getReorderedItemsParent() { - return reorderedItemsParent; + public Component getItem() { + return item; } /** - * Returns the list of the reordered item and its sibling items + * Returns the root level items of the dashboard * - * @return the list of the reordered item and its sibling items + * @return the root level items of the dashboard */ - public List getReorderedItems() { - return reorderedItems; - } - - private List getReorderedItemsList( - JsonArray reorderedItemsFromClient) { - Objects.requireNonNull(reorderedItemsFromClient); - Map nodeIdToItems = reorderedItemsParent - .getChildren() - .collect(Collectors.toMap( - item -> item.getElement().getNode().getId(), - Function.identity())); - List items = new ArrayList<>(); - for (int index = 0; index < reorderedItemsFromClient - .length(); index++) { - int nodeIdFromClient = (int) ((JsonObject) reorderedItemsFromClient - .get(index)).getNumber("nodeid"); - items.add(nodeIdToItems.get(nodeIdFromClient)); - } + public List getItems() { return items; } - private static JsonArray getSectionItems(JsonArray items, - int sectionNodeId) { - for (int rootLevelIdx = 0; rootLevelIdx < items - .length(); rootLevelIdx++) { - JsonObject item = items.get(rootLevelIdx); - int itemNodeId = (int) item.getNumber("nodeid"); - if (sectionNodeId == itemNodeId) { - JsonObject sectionObj = items.get(rootLevelIdx); - return sectionObj.getArray("items"); - } - } - return null; + /** + * Returns the section that contains the moved item, or an empty optional if + * the item is a direct child of the dashboard + * + * @return the section that contains the moved item, or an empty optional if + * the item is a direct child of the dashboard + */ + public Optional getSection() { + return Optional.ofNullable(section); } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemRemovedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemRemovedEvent.java index 8702a08ecfe..e270d45554b 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemRemovedEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemRemovedEvent.java @@ -8,13 +8,11 @@ */ package com.vaadin.flow.component.dashboard; -import java.util.Objects; +import java.util.List; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.ComponentEvent; import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; -import com.vaadin.flow.component.EventData; /** * Widget or section removed event of {@link Dashboard}. @@ -22,10 +20,11 @@ * @author Vaadin Ltd. * @see Dashboard#addItemRemovedListener(ComponentEventListener) */ -@DomEvent("dashboard-item-removed") public class DashboardItemRemovedEvent extends ComponentEvent { - private final Component removedItem; + private final Component item; + + private final List items; /** * Creates a dashboard item removed event. @@ -33,13 +32,18 @@ public class DashboardItemRemovedEvent extends ComponentEvent { * @param source * Dashboard that contains the item that was removed * @param fromClient - * true if the event originated from the client - * side, false otherwise + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param item + * The removed item + * @param items + * The root level items of the dashboard */ public DashboardItemRemovedEvent(Dashboard source, boolean fromClient, - @EventData("event.detail.item.nodeid") int nodeId) { + Component item, List items) { super(source, fromClient); - this.removedItem = getRemovedItem(source, nodeId); + this.item = item; + this.items = items; } /** @@ -47,22 +51,16 @@ public DashboardItemRemovedEvent(Dashboard source, boolean fromClient, * * @return the removed item */ - public Component getRemovedItem() { - return removedItem; + public Component getItem() { + return item; } - private static Component getRemovedItem(Dashboard dashboard, int nodeId) { - return dashboard.getChildren().map(item -> { - if (nodeId == item.getElement().getNode().getId()) { - return item; - } - if (item instanceof DashboardSection section) { - return section.getWidgets().stream() - .filter(sectionItem -> nodeId == sectionItem - .getElement().getNode().getId()) - .findAny().orElse(null); - } - return null; - }).filter(Objects::nonNull).findAny().orElse(null); + /** + * Returns the root level items of the dashboard + * + * @return the root level items of the dashboard + */ + public List getItems() { + return items; } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java index 0d66ee06a57..ba34d7976e9 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizedEvent.java @@ -8,10 +8,11 @@ */ package com.vaadin.flow.component.dashboard; +import java.util.List; + +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.ComponentEvent; import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.DomEvent; -import com.vaadin.flow.component.EventData; /** * Widget resized event of {@link Dashboard}. @@ -19,14 +20,11 @@ * @author Vaadin Ltd. * @see Dashboard#addItemResizedListener(ComponentEventListener) */ -@DomEvent("dashboard-item-resized") public class DashboardItemResizedEvent extends ComponentEvent { - private final DashboardWidget resizedWidget; - - private final int colspan; + private final DashboardWidget item; - private final int rowspan; + private final List items; /** * Creates a dashboard item resized event. @@ -34,25 +32,18 @@ public class DashboardItemResizedEvent extends ComponentEvent { * @param source * Dashboard that contains the widget that was resized * @param fromClient - * true if the event originated from the client - * side, false otherwise - * @param nodeId - * Node ID the resized widget - * @param colspan - * New colspan of the resized widget - * @param rowspan - * New rowspan of the resized widget + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param item + * The resized widget + * @param items + * The root level items of the dashboard */ public DashboardItemResizedEvent(Dashboard source, boolean fromClient, - @EventData("event.detail.item.nodeid") int nodeId, - @EventData("event.detail.item.colspan") int colspan, - @EventData("event.detail.item.rowspan") int rowspan) { + DashboardWidget item, List items) { super(source, fromClient); - this.resizedWidget = source.getWidgets().stream() - .filter(child -> nodeId == child.getElement().getNode().getId()) - .findAny().orElse(null); - this.colspan = colspan; - this.rowspan = rowspan; + this.item = item; + this.items = items; } /** @@ -60,25 +51,16 @@ public DashboardItemResizedEvent(Dashboard source, boolean fromClient, * * @return the resized widget */ - public DashboardWidget getResizedWidget() { - return resizedWidget; - } - - /** - * Returns the new colspan of the resized item - * - * @return new colspan of the resized item - */ - public int getColspan() { - return colspan; + public DashboardWidget getItem() { + return item; } /** - * Returns the new rowspan of the resized item + * Returns the root level items of the dashboard * - * @return new rowspan of the resized item + * @return the root level items of the dashboard */ - public int getRowspan() { - return rowspan; + public List getItems() { + return items; } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java index 0adf255ed5d..35f036a0641 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java @@ -10,17 +10,21 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.vaadin.flow.component.ComponentUtil; +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.dashboard.Dashboard; -import com.vaadin.flow.component.dashboard.DashboardItemMovedEvent; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; +import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.internal.nodefeature.ElementListenerMap; import elemental.json.Json; import elemental.json.JsonArray; @@ -73,19 +77,124 @@ public void reorderWidgetInSectionToSamePosition_orderIsNotUpdated() { @Test public void setDashboardNotEditable_reorderWidget_orderIsNotUpdated() { dashboard.setEditable(false); + int movedWidgetNodeId = dashboard.getChildren().toList().get(0) + .getElement().getNode().getId(); List expectedRootLevelNodeIds = getRootLevelNodeIds(); reorderRootLevelItem(0, 1); - fireItemMovedEvent(); + fireItemMovedEvent(movedWidgetNodeId); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } - private void fireItemMovedEvent() { - fireItemMovedEvent(null); + @Test + public void reorderWidget_eventCorrectlyFired() { + int initialIndex = 0; + int finalIndex = 1; + Component movedItem = dashboard.getChildren().toList() + .get(initialIndex); + int movedItemNodeId = movedItem.getElement().getNode().getId(); + List expectedItems = dashboard.getChildren() + .collect(Collectors.toCollection(ArrayList::new)); + expectedItems.add(finalIndex, expectedItems.remove(initialIndex)); + Runnable itemMoveAction = () -> { + reorderRootLevelItem(initialIndex, finalIndex); + fireItemMovedEvent(movedItemNodeId); + }; + assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, + null); + } + + @Test + public void reorderSection_eventCorrectlyFired() { + int initialIndex = 2; + int finalIndex = 1; + Component movedItem = dashboard.getChildren().toList() + .get(initialIndex); + int movedItemNodeId = movedItem.getElement().getNode().getId(); + List expectedItems = dashboard.getChildren() + .collect(Collectors.toCollection(ArrayList::new)); + expectedItems.add(finalIndex, expectedItems.remove(initialIndex)); + Runnable itemMoveAction = () -> { + reorderRootLevelItem(initialIndex, finalIndex); + fireItemMovedEvent(movedItemNodeId); + }; + assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, + null); + } + + @Test + public void reorderWidgetInSection_eventCorrectlyFired() { + int sectionIndex = 2; + int initialIndex = 0; + int finalIndex = 1; + List expectedItems = dashboard.getChildren().toList(); + DashboardSection section = (DashboardSection) expectedItems + .get(sectionIndex); + int sectionNodeId = section.getElement().getNode().getId(); + Component movedItem = section.getWidgets().get(initialIndex); + int movedItemNodeId = movedItem.getElement().getNode().getId(); + Runnable itemMoveAction = () -> { + reorderSectionWidget(sectionIndex, initialIndex, finalIndex); + fireItemMovedEvent(movedItemNodeId, sectionNodeId); + }; + assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, + section); } - private void fireItemMovedEvent(Integer sectionNodeId) { - ComponentUtil.fireEvent(dashboard, new DashboardItemMovedEvent( - dashboard, false, itemsArray, sectionNodeId)); + @Test + public void setDashboardNotEditable_reorderWidget_eventNotFired() { + dashboard.setEditable(false); + int initialIndex = 0; + int finalIndex = 1; + Component movedItem = dashboard.getChildren().toList() + .get(initialIndex); + int movedItemNodeId = movedItem.getElement().getNode().getId(); + Runnable itemMoveAction = () -> { + reorderRootLevelItem(initialIndex, finalIndex); + fireItemMovedEvent(movedItemNodeId); + }; + assertEventCorrectlyFired(itemMoveAction, 0, null, null, null); + } + + private void assertEventCorrectlyFired(Runnable itemMoveAction, + int expectedListenerInvokedCount, Component expectedItem, + List expectedItems, DashboardSection expectedSection) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventItem = new AtomicReference<>(); + AtomicReference> eventItems = new AtomicReference<>(); + AtomicReference> eventSection = new AtomicReference<>(); + dashboard.addItemMovedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventItem.set(e.getItem()); + eventItems.set(e.getItems()); + eventSection.set(e.getSection()); + e.unregisterListener(); + }); + itemMoveAction.run(); + Assert.assertEquals(expectedListenerInvokedCount, + listenerInvokedCount.get()); + if (expectedListenerInvokedCount > 0) { + Assert.assertEquals(expectedItem, eventItem.get()); + Assert.assertEquals(expectedItems, eventItems.get()); + Assert.assertEquals(Optional.ofNullable(expectedSection), + eventSection.get()); + } + } + + private void fireItemMovedEvent(int itemNodeId) { + fireItemMovedEvent(itemNodeId, null); + } + + private void fireItemMovedEvent(int itemNodeId, Integer sectionNodeId) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item", itemNodeId); + eventData.put("event.detail.items", itemsArray); + if (sectionNodeId != null) { + eventData.put("event.detail.section", sectionNodeId); + } + DomEvent itemMovedDomEvent = new DomEvent(dashboard.getElement(), + "dashboard-item-moved-flow", eventData); + dashboard.getElement().getNode().getFeature(ElementListenerMap.class) + .fireEvent(itemMovedDomEvent); } private List getSectionWidgetNodeIds(int sectionIndex) { @@ -136,21 +245,26 @@ private void reorderRootLevelItem(int initialIndex, int finalIndex) { private void assertSectionWidgetReorder(int sectionIndex, int initialIndex, int finalIndex) { - int sectionNodeId = dashboard.getChildren().toList().get(sectionIndex) + DashboardSection section = (DashboardSection) dashboard.getChildren() + .toList().get(sectionIndex); + int sectionNodeId = section.getElement().getNode().getId(); + int movedWidgetNodeId = section.getWidgets().get(initialIndex) .getElement().getNode().getId(); reorderSectionWidget(sectionIndex, initialIndex, finalIndex); List expectedSectionWidgetNodeIds = getExpectedSectionWidgetNodeIds( sectionIndex, initialIndex, finalIndex); - fireItemMovedEvent(sectionNodeId); + fireItemMovedEvent(movedWidgetNodeId, sectionNodeId); Assert.assertEquals(expectedSectionWidgetNodeIds, getSectionWidgetNodeIds(sectionIndex)); } private void assertRootLevelItemReorder(int initialIndex, int finalIndex) { + int movedItemNodeId = dashboard.getChildren().toList().get(initialIndex) + .getElement().getNode().getId(); reorderRootLevelItem(initialIndex, finalIndex); List expectedRootLevelNodeIds = getExpectedRootLevelItemNodeIds( initialIndex, finalIndex); - fireItemMovedEvent(); + fireItemMovedEvent(movedItemNodeId); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java index 5345f7947d3..7a396a7e4bb 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java @@ -8,15 +8,23 @@ */ package com.vaadin.flow.component.dashboard.tests; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.vaadin.flow.component.ComponentUtil; +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.dashboard.Dashboard; -import com.vaadin.flow.component.dashboard.DashboardItemResizedEvent; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; +import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.internal.nodefeature.ElementListenerMap; + +import elemental.json.Json; +import elemental.json.JsonObject; public class DashboardDragResizeTest extends DashboardTestBase { private Dashboard dashboard; @@ -73,6 +81,53 @@ public void setDashboardNotEditable_resizeWidget_sizeIsNotUpdated() { Assert.assertEquals(1, widgetToResize.getRowspan()); } + @Test + public void resizeWidget_eventCorrectlyFired() { + DashboardWidget resizedWidget = (DashboardWidget) dashboard + .getChildren().toList().get(0); + assertEventCorrectlyFired(resizedWidget, 1, resizedWidget, + dashboard.getChildren().toList()); + } + + @Test + public void resizeWidgetInSection_eventCorrectlyFired() { + DashboardSection section = (DashboardSection) dashboard.getChildren() + .toList().get(1); + DashboardWidget resizedWidget = section.getWidgets().get(0); + assertEventCorrectlyFired(resizedWidget, 1, resizedWidget, + dashboard.getChildren().toList()); + } + + @Test + public void setDashboardNotEditable_resizeWidget_eventNotFired() { + dashboard.setEditable(false); + DashboardWidget resizedWidget = (DashboardWidget) dashboard + .getChildren().toList().get(0); + assertEventCorrectlyFired(resizedWidget, 0, null, null); + } + + private void assertEventCorrectlyFired(DashboardWidget widgetToResize, + int expectedListenerInvokedCount, Component expectedResizedWidget, + List expectedItems) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventResizedWidget = new AtomicReference<>(); + AtomicReference> eventItems = new AtomicReference<>(); + dashboard.addItemResizedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventResizedWidget.set(e.getItem()); + eventItems.set(e.getItems()); + e.unregisterListener(); + }); + fireItemResizedEvent(widgetToResize, 2, 2); + Assert.assertEquals(expectedListenerInvokedCount, + listenerInvokedCount.get()); + if (expectedListenerInvokedCount > 0) { + Assert.assertEquals(expectedResizedWidget, + eventResizedWidget.get()); + Assert.assertEquals(expectedItems, eventItems.get()); + } + } + private void assertWidgetResized(int widgetIndexToResize, int targetColspan, int targetRowspan) { DashboardWidget widgetToResize = dashboard.getWidgets() @@ -89,9 +144,14 @@ private void assertWidgetResized(int widgetIndexToResize, int targetColspan, private void fireItemResizedEvent(DashboardWidget widget, int targetColspan, int targetRowspan) { - ComponentUtil.fireEvent(dashboard, - new DashboardItemResizedEvent(dashboard, false, - widget.getElement().getNode().getId(), targetColspan, - targetRowspan)); + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", + widget.getElement().getNode().getId()); + eventData.put("event.detail.item.rowspan", targetRowspan); + eventData.put("event.detail.item.colspan", targetColspan); + DomEvent itemResizedDomEvent = new DomEvent(dashboard.getElement(), + "dashboard-item-resized", eventData); + dashboard.getElement().getNode().getFeature(ElementListenerMap.class) + .fireEvent(itemResizedDomEvent); } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java index b6cdaf46836..5d800801a57 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java @@ -8,19 +8,27 @@ */ package com.vaadin.flow.component.dashboard.tests; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.vaadin.flow.component.ComponentUtil; +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.dashboard.Dashboard; -import com.vaadin.flow.component.dashboard.DashboardItemRemovedEvent; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.internal.nodefeature.ElementListenerMap; + +import elemental.json.Json; +import elemental.json.JsonObject; public class DashboardTest extends DashboardTestBase { private Dashboard dashboard; @@ -852,6 +860,56 @@ public void setDashboardEditable_removeWidget_widgetIsRemoved() { Assert.assertFalse(actualNodeIds.contains(nodeIdToBeRemoved)); } + public void setDashboardEditable_removeWidget_eventCorrectlyFired() { + dashboard.setEditable(true); + DashboardWidget widget = new DashboardWidget(); + dashboard.add(widget); + fakeClientCommunication(); + int removedWidgetNodeId = widget.getElement().getNode().getId(); + List expectedItems = dashboard.getChildren() + .collect(Collectors.toCollection(ArrayList::new)); + expectedItems.remove(widget); + assertItemRemoveEventCorrectlyFired(removedWidgetNodeId, 1, widget, + expectedItems); + } + + @Test + public void setDashboardEditable_removeSection_eventCorrectlyFired() { + dashboard.setEditable(true); + DashboardSection section = dashboard.addSection(); + fakeClientCommunication(); + int removedSectionNodeId = section.getElement().getNode().getId(); + List expectedItems = dashboard.getChildren() + .collect(Collectors.toCollection(ArrayList::new)); + expectedItems.remove(section); + assertItemRemoveEventCorrectlyFired(removedSectionNodeId, 1, section, + expectedItems); + } + + @Test + public void setDashboardEditable_removeWidgetInSection_eventCorrectlyFired() { + dashboard.setEditable(true); + DashboardSection section = dashboard.addSection(); + DashboardWidget widget = new DashboardWidget(); + section.add(widget); + fakeClientCommunication(); + int removedWidgetNodeId = widget.getElement().getNode().getId(); + List expectedItems = dashboard.getChildren() + .collect(Collectors.toCollection(ArrayList::new)); + expectedItems.remove(widget); + assertItemRemoveEventCorrectlyFired(removedWidgetNodeId, 1, widget, + expectedItems); + } + + @Test + public void dashboardNotEditable_removeWidget_eventNotFired() { + DashboardWidget widget = new DashboardWidget(); + dashboard.add(widget); + fakeClientCommunication(); + int removedWidgetNodeId = widget.getElement().getNode().getId(); + assertItemRemoveEventCorrectlyFired(removedWidgetNodeId, 0, null, null); + } + @Test public void setDashboardVisibility_exceptionIsThrown() { Assert.assertThrows(UnsupportedOperationException.class, @@ -879,9 +937,34 @@ public void getSectionVisibility_returnsTrue() { DashboardSection section = dashboard.addSection(); Assert.assertTrue(section.isVisible()); } + + private void assertItemRemoveEventCorrectlyFired(int nodeIdToRemove, + int expectedListenerInvokedCount, Component expectedRemovedItem, + List expectedItems) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventRemovedItem = new AtomicReference<>(); + AtomicReference> eventItems = new AtomicReference<>(); + dashboard.addItemRemovedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventRemovedItem.set(e.getItem()); + eventItems.set(e.getItems()); + e.unregisterListener(); + }); + fireItemRemovedEvent(nodeIdToRemove); + Assert.assertEquals(expectedListenerInvokedCount, + listenerInvokedCount.get()); + if (expectedListenerInvokedCount > 0) { + Assert.assertEquals(expectedRemovedItem, eventRemovedItem.get()); + Assert.assertEquals(expectedItems, eventItems.get()); + } + } private void fireItemRemovedEvent(int nodeId) { - ComponentUtil.fireEvent(dashboard, - new DashboardItemRemovedEvent(dashboard, false, nodeId)); + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", nodeId); + DomEvent itemRemovedDomEvent = new DomEvent(dashboard.getElement(), + "dashboard-item-removed", eventData); + dashboard.getElement().getNode().getFeature(ElementListenerMap.class) + .fireEvent(itemRemovedDomEvent); } } From a15ddab890ecbe550b5793d47b039d77894c301e Mon Sep 17 00:00:00 2001 From: ugur-vaadin Date: Tue, 24 Sep 2024 09:45:46 +0300 Subject: [PATCH 7/7] chore: run formatter --- .../flow/component/dashboard/tests/DashboardTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java index 5d800801a57..8c73e5eabd5 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java @@ -937,10 +937,10 @@ public void getSectionVisibility_returnsTrue() { DashboardSection section = dashboard.addSection(); Assert.assertTrue(section.isVisible()); } - + private void assertItemRemoveEventCorrectlyFired(int nodeIdToRemove, - int expectedListenerInvokedCount, Component expectedRemovedItem, - List expectedItems) { + int expectedListenerInvokedCount, Component expectedRemovedItem, + List expectedItems) { AtomicInteger listenerInvokedCount = new AtomicInteger(0); AtomicReference eventRemovedItem = new AtomicReference<>(); AtomicReference> eventItems = new AtomicReference<>();