Implemented buckets list component
This commit is contained in:
parent
f4c32dff24
commit
1058039e54
@ -0,0 +1,142 @@
|
|||||||
|
package ru.dragonestia.loadbalancer.web.component;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.dialog.Dialog;
|
||||||
|
import com.vaadin.flow.component.grid.ColumnTextAlign;
|
||||||
|
import com.vaadin.flow.component.grid.Grid;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.html.Span;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
|
import com.vaadin.flow.component.notification.NotificationVariant;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import ru.dragonestia.loadbalancer.web.model.Bucket;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BucketList extends VerticalLayout {
|
||||||
|
|
||||||
|
private final Grid<Bucket> bucketsGrid;
|
||||||
|
private final TextField searchField;
|
||||||
|
private List<Bucket> cachedBuckets;
|
||||||
|
|
||||||
|
public BucketList(List<Bucket> buckets) {
|
||||||
|
cachedBuckets = buckets;
|
||||||
|
|
||||||
|
add(new H2("Buckets"));
|
||||||
|
add(searchField = createSearchField());
|
||||||
|
add(bucketsGrid = createGrid());
|
||||||
|
|
||||||
|
update(buckets);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField createSearchField() {
|
||||||
|
var field = new TextField("Search bucket");
|
||||||
|
field.setPrefixComponent(new Icon(VaadinIcon.SEARCH));
|
||||||
|
field.setClearButtonVisible(true);
|
||||||
|
field.setHelperText("Press Enter to search");
|
||||||
|
field.addValueChangeListener(event -> applySearch(event.getValue()));
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySearch(String input) {
|
||||||
|
var temp = input.trim();
|
||||||
|
|
||||||
|
bucketsGrid.setItems(cachedBuckets.stream()
|
||||||
|
.filter(bucket -> bucket.getIdentifier().startsWith(temp))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Grid<Bucket> createGrid() {
|
||||||
|
var grid = new Grid<>(Bucket.class, false);
|
||||||
|
grid.addColumn(Bucket::getIdentifier).setHeader("Identifier");
|
||||||
|
grid.addComponentColumn(bucket -> {
|
||||||
|
var result = new Span();
|
||||||
|
if (bucket.getSlots().isUnlimited()) {
|
||||||
|
result.setText("Unlimited");
|
||||||
|
result.getElement().getThemeList().add("badge contrast");
|
||||||
|
} else {
|
||||||
|
result.setText(Integer.toString(bucket.getSlots().getSlots()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}).setHeader("Slots").setTextAlign(ColumnTextAlign.CENTER);
|
||||||
|
grid.addComponentColumn(this::createManageButtons).setHeader("Manage");
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HorizontalLayout createManageButtons(Bucket bucket) {
|
||||||
|
var layout = new HorizontalLayout();
|
||||||
|
|
||||||
|
{
|
||||||
|
var button = new Button("Details");
|
||||||
|
button.addClickListener(event -> clickDetailsButton(bucket));
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
layout.add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var button = new Button("Remove");
|
||||||
|
button.addClickListener(event -> clickRemoveButton(bucket));
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
layout.add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickDetailsButton(Bucket bucket) {
|
||||||
|
getUI().ifPresent(ui -> {
|
||||||
|
ui.navigate("/nodes/" + bucket.getNodeIdentifier() +
|
||||||
|
"/" + bucket.getIdentifier());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickRemoveButton(Bucket bucket) {
|
||||||
|
var dialog = new Dialog("Confirm bucket deletion");
|
||||||
|
dialog.add(new Paragraph("Confirm that you want to delete bucket. Enter '" + bucket.getIdentifier() + "' to field below and confirm."));
|
||||||
|
|
||||||
|
var inputField = new TextField();
|
||||||
|
dialog.add(inputField);
|
||||||
|
|
||||||
|
{ // confirm
|
||||||
|
var button = new Button("Confirm");
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
button.addClickListener(event -> {
|
||||||
|
if (!bucket.getIdentifier().equals(inputField.getValue())) {
|
||||||
|
Notification.show("Invalid input", 3000, Notification.Position.TOP_END)
|
||||||
|
.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBucket(bucket);
|
||||||
|
Notification.show("Bucket '" + bucket.getIdentifier() + "' was successfully removed!", 3000, Notification.Position.TOP_END)
|
||||||
|
.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||||
|
dialog.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.getFooter().add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // cancel
|
||||||
|
var button = new Button("Cancel", event -> dialog.close());
|
||||||
|
button.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||||
|
dialog.getFooter().add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(List<Bucket> buckets) {
|
||||||
|
cachedBuckets = buckets;
|
||||||
|
applySearch(searchField.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeBucket(Bucket bucket) {
|
||||||
|
// TODO: send remove request and getting list
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
package ru.dragonestia.loadbalancer.web.component;
|
package ru.dragonestia.loadbalancer.web.component;
|
||||||
|
|
||||||
import com.vaadin.flow.component.Component;
|
import com.vaadin.flow.component.Component;
|
||||||
import com.vaadin.flow.component.UI;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.html.Span;
|
import com.vaadin.flow.component.html.Span;
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import com.vaadin.flow.component.notification.NotificationVariant;
|
|||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
import com.vaadin.flow.component.textfield.TextFieldVariant;
|
|
||||||
import ru.dragonestia.loadbalancer.web.model.Node;
|
import ru.dragonestia.loadbalancer.web.model.Node;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -82,7 +81,7 @@ public class NodeList extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clickDetailsButton(Node node) {
|
private void clickDetailsButton(Node node) {
|
||||||
// TODO
|
getUI().ifPresent(ui -> ui.navigate("/nodes/" + node.identifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clickRemoveButton(Node node) {
|
private void clickRemoveButton(Node node) {
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
package ru.dragonestia.loadbalancer.web.page;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||||
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.loadbalancer.web.component.BucketList;
|
||||||
|
import ru.dragonestia.loadbalancer.web.component.NavPath;
|
||||||
|
import ru.dragonestia.loadbalancer.web.model.Bucket;
|
||||||
|
import ru.dragonestia.loadbalancer.web.model.Node;
|
||||||
|
import ru.dragonestia.loadbalancer.web.model.type.LoadBalancingMethod;
|
||||||
|
import ru.dragonestia.loadbalancer.web.model.type.SlotLimit;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@PageTitle("Buckets")
|
||||||
|
@Route("/nodes/:nodeId")
|
||||||
|
public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
||||||
|
|
||||||
|
private Node node;
|
||||||
|
private BucketList bucketList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEnter(BeforeEnterEvent event) {
|
||||||
|
var nodeIdOpt = event.getRouteParameters().get("nodeId");
|
||||||
|
if (nodeIdOpt.isEmpty()) {
|
||||||
|
getUI().ifPresent(ui -> ui.navigate("/nodes"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node = new Node(nodeIdOpt.get(), LoadBalancingMethod.ROUND_ROBIN); // TODO: getting node
|
||||||
|
|
||||||
|
add(new NavPath(new NavPath.Point("Nodes", "/nodes"),
|
||||||
|
new NavPath.Point(node.identifier(), "/nodes/" + node.identifier())));
|
||||||
|
|
||||||
|
// TODO: getting buckets
|
||||||
|
add(bucketList = new BucketList(List.of(
|
||||||
|
Bucket.create("test-1", node, SlotLimit.unlimited(), "Hello world!"),
|
||||||
|
Bucket.create("test-2", node, SlotLimit.of(12), "Hello world!"),
|
||||||
|
Bucket.create("test-3", node, SlotLimit.unlimited(), "Hello world!"),
|
||||||
|
Bucket.create("test-4", node, SlotLimit.of(32), "Hello world!"),
|
||||||
|
Bucket.create("test-5", node, SlotLimit.of(54), "Hello world!")
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user