Skip to content

Commit

Permalink
feat: support dashboard item remove using button (#6650)
Browse files Browse the repository at this point in the history
* feat: support dashboard item remove using button

* test: remove tests about visibility of edit buttons
  • Loading branch information
ugur-vaadin committed Oct 15, 2024
1 parent 6ae4942 commit 4a5c1e0
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ public DashboardDragReorderPage() {
});
toggleAttached.setId("toggle-attached");

NativeButton toggleEditable = new NativeButton("Toggle editable",
e -> dashboard.setEditable(!dashboard.isEditable()));
toggleEditable.setId("toggle-editable");

add(toggleAttached, toggleEditable, dashboard);
add(toggleAttached, dashboard);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
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.component.html.NativeButton;
import com.vaadin.flow.router.Route;

/**
Expand All @@ -37,10 +36,6 @@ public DashboardDragResizePage() {
DashboardSection section = dashboard.addSection("Section");
section.add(widgetInSection);

NativeButton toggleEditable = new NativeButton("Toggle editable",
e -> dashboard.setEditable(!dashboard.isEditable()));
toggleEditable.setId("toggle-editable");

add(toggleEditable, dashboard);
add(dashboard);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,14 @@ public DashboardPage() {
click -> dashboard.setMaximumColumnCount(null));
setMaximumColumnCountNull.setId("set-maximum-column-count-null");

NativeButton toggleEditable = new NativeButton("Toggle editable",
e -> dashboard.setEditable(!dashboard.isEditable()));
toggleEditable.setId("toggle-editable");

add(addMultipleWidgets, removeFirstAndLastWidgets, removeAll,
addSectionWithMultipleWidgets, removeFirstSection,
setMaximumColumnCount1, setMaximumColumnCountNull, dashboard);
setMaximumColumnCount1, setMaximumColumnCountNull,
toggleEditable, dashboard);
}

private static Optional<DashboardSection> getFirstSection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,6 @@ public void detachReattach_reorderWidgetOnClientSide_itemsAreReorderedCorrectly(
reorderWidgetOnClientSide_itemsAreReorderedCorrectly();
}

@Test
public void setDashboardNotEditable_dragHandleNotVisible() {
var widget = dashboardElement.getWidgets().get(0);
Assert.assertTrue(isDragHandleVisible(widget));
clickElementWithJs("toggle-editable");
Assert.assertFalse(isDragHandleVisible(widget));
}

@Test
public void setDashboardEditable_dragHandleNotVisible() {
clickElementWithJs("toggle-editable");
clickElementWithJs("toggle-editable");
Assert.assertTrue(
isDragHandleVisible(dashboardElement.getWidgets().get(0)));
}

private void dragResizeElement(TestBenchElement draggedElement,
TestBenchElement targetElement) {
var dragHandle = getDragHandle(draggedElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,6 @@ public void resizeWidgetInSectionBothHorizontallyAndVertically_widgetIsResizedCo
assertWidgetResized(1);
}

@Test
public void setDashboardNotEditable_resizeHandleNotVisible() {
var widget = dashboardElement.getWidgets().get(0);
Assert.assertTrue(isResizeHandleVisible(widget));
clickElementWithJs("toggle-editable");
Assert.assertFalse(isResizeHandleVisible(widget));
}

@Test
public void setDashboardEditable_resizeHandleNotVisible() {
clickElementWithJs("toggle-editable");
clickElementWithJs("toggle-editable");
Assert.assertTrue(
isResizeHandleVisible(dashboardElement.getWidgets().get(0)));
}

private void assertWidgetResized(int widgetIndexToResize) {
var widgetToResize = dashboardElement.getWidgets()
.get(widgetIndexToResize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.vaadin.flow.component.dashboard.testbench.DashboardSectionElement;
import com.vaadin.flow.component.dashboard.testbench.DashboardWidgetElement;
import com.vaadin.flow.testutil.TestPath;
import com.vaadin.testbench.TestBenchElement;
import com.vaadin.tests.AbstractComponentIT;

/**
Expand Down Expand Up @@ -57,6 +58,27 @@ public void removeFirstAndLastWidgetsFromDashboard_widgetsAreCorrectlyRemoved()
"Widget 1 in Section 1", "Widget 2 in Section 1");
}

@Test
public void removeWidgetUsingButton_widgetIsRemoved() {
clickElementWithJs("toggle-editable");
DashboardWidgetElement widgetToRemove = dashboardElement.getWidgets()
.get(0);
getRemoveButton(widgetToRemove).click();
assertDashboardWidgetsByTitle("Widget 2", "Widget 3",
"Widget 1 in Section 1", "Widget 2 in Section 1",
"Widget 1 in Section 2");
}

@Test
public void removeWidgetInSectionUsingButton_widgetIsRemoved() {
clickElementWithJs("toggle-editable");
DashboardSectionElement section = dashboardElement.getSections().get(0);
DashboardWidgetElement widgetToRemove = section.getWidgets().get(0);
getRemoveButton(widgetToRemove).click();
assertDashboardWidgetsByTitle("Widget 1", "Widget 2", "Widget 3",
"Widget 2 in Section 1", "Widget 1 in Section 2");
}

@Test
public void removeAllFromDashboard_widgetsAnsSectionsAreCorrectlyRemoved() {
clickElementWithJs("remove-all");
Expand Down Expand Up @@ -100,6 +122,20 @@ public void removeFirstSection_sectionIsRemoved() {
assertSectionWidgetsByTitle(firstSection, "Widget 1 in Section 2");
}

@Test
public void removeFirstSectionUsingButton_sectionIsRemoved() {
clickElementWithJs("toggle-editable");
DashboardSectionElement sectionToRemove = dashboardElement.getSections()
.get(0);
String sectionTitle = sectionToRemove.getTitle();
getRemoveButton(sectionToRemove).click();
assertDashboardWidgetsByTitle("Widget 1", "Widget 2", "Widget 3",
"Widget 1 in Section 2");
List<String> sectionTitles = dashboardElement.getSections().stream()
.map(DashboardSectionElement::getTitle).toList();
Assert.assertFalse(sectionTitles.contains(sectionTitle));
}

@Test
public void changeMaximumColumnCountTo1_widgetsShouldBeOnTheSameColumn() {
List<DashboardWidgetElement> widgets = dashboardElement.getWidgets();
Expand Down Expand Up @@ -144,4 +180,8 @@ private static void assertWidgetsByTitle(
.map(DashboardWidgetElement::getTitle).toList();
Assert.assertEquals(Arrays.asList(expectedWidgetTitles), widgetTitles);
}

private static TestBenchElement getRemoveButton(TestBenchElement element) {
return element.$("button").withId("remove-button").first();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public Dashboard() {
childDetachHandler = getChildDetachHandler();
addItemReorderEndListener(this::onItemReorderEnd);
addItemResizeEndListener(this::onItemResizeEnd);
addItemRemovedListener(this::onItemRemoved);
}

/**
Expand Down Expand Up @@ -350,6 +351,18 @@ public Registration addItemResizeEndListener(
return addListener(DashboardItemResizeEndEvent.class, listener);
}

/**
* Adds an item removed listener to this dashboard.
*
* @param listener
* the listener to add, not <code>null</code>
* @return a handle that can be used for removing the listener
*/
public Registration addItemRemovedListener(
ComponentEventListener<DashboardItemRemovedEvent> listener) {
return addListener(DashboardItemRemovedEvent.class, listener);
}

@Override
public Stream<Component> getChildren() {
return childrenComponents.stream();
Expand Down Expand Up @@ -480,6 +493,11 @@ private void onItemResizeEnd(
resizedWidget.setColspan(dashboardItemResizeEndEvent.getColspan());
}

private void onItemRemoved(
DashboardItemRemovedEvent dashboardItemRemovedEvent) {
dashboardItemRemovedEvent.getRemovedItem().removeFromParent();
}

private void reorderItems(JsonArray orderedItemsFromClient) {
// Keep references to the root level children before clearing them
Map<Integer, Component> nodeIdToComponent = childrenComponents.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright 2000-2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
* license.
*/
package com.vaadin.flow.component.dashboard;

import java.util.Objects;

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}.
*
* @author Vaadin Ltd.
* @see Dashboard#addItemRemovedListener(ComponentEventListener)
*/
@DomEvent("dashboard-item-removed")
public class DashboardItemRemovedEvent extends ComponentEvent<Dashboard> {

private final Component removedItem;

/**
* Creates a dashboard item removed event.
*
* @param source
* Dashboard that contains the item that was removed
* @param fromClient
* <code>true</code> if the event originated from the client
* side, <code>false</code> otherwise
*/
public DashboardItemRemovedEvent(Dashboard source, boolean fromClient,
@EventData("event.detail.item.nodeid") int nodeId) {
super(source, fromClient);
this.removedItem = getRemovedItem(source, nodeId);
}

/**
* Returns the removed item
*
* @return the removed item
*/
public Component getRemovedItem() {
return removedItem;
}

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ private void assertSectionWidgetReorder(int sectionIndex, int initialIndex,
}

private void assertRootLevelItemReorder(int initialIndex, int finalIndex) {

reorderRootLevelItem(initialIndex, finalIndex);
List<Integer> expectedRootLevelNodeIds = getExpectedRootLevelItemNodeIds(
initialIndex, finalIndex);
Expand Down

0 comments on commit 4a5c1e0

Please sign in to comment.