Added Accounts page
This commit is contained in:
parent
11ef2b51c9
commit
bbd55ed8b3
@ -0,0 +1,190 @@
|
||||
package ru.dragonestia.picker.cp.component;
|
||||
|
||||
import com.vaadin.flow.component.Unit;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
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.H3;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.PasswordField;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.theme.lumo.LumoIcon;
|
||||
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
||||
import ru.dragonestia.picker.api.repository.AccountRepository;
|
||||
import ru.dragonestia.picker.cp.model.Permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AccountList extends VerticalLayout implements RefreshableTable {
|
||||
|
||||
private final AccountRepository accountRepository;
|
||||
private final TextField searchField;
|
||||
private final Grid<ResponseAccount> grid;
|
||||
|
||||
private List<ResponseAccount> cachedAccounts = new ArrayList<>();
|
||||
|
||||
public AccountList(AccountRepository accountRepository) {
|
||||
this.accountRepository = accountRepository;
|
||||
|
||||
add(searchField = createSearchField());
|
||||
add(grid = createGridAccounts());
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
private TextField createSearchField() {
|
||||
var field = new TextField("Search by account username");
|
||||
field.setPrefixComponent(new Icon(VaadinIcon.SEARCH));
|
||||
field.setClearButtonVisible(true);
|
||||
field.setHelperText("Press Enter to search");
|
||||
field.addValueChangeListener(event -> applySearch(event.getValue()));
|
||||
field.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
field.setMinWidth(30, Unit.PERCENTAGE);
|
||||
return field;
|
||||
}
|
||||
|
||||
private Grid<ResponseAccount> createGridAccounts() {
|
||||
var grid = new Grid<>(ResponseAccount.class, false);
|
||||
|
||||
grid.addColumn(ResponseAccount::getUsername).setHeader("Username")
|
||||
.setComparator(Comparator.comparing(ResponseAccount::getUsername)).setSortable(true);
|
||||
|
||||
grid.addComponentColumn(this::createAccountManagementButtons).setFrozenToEnd(true)
|
||||
.setTextAlign(ColumnTextAlign.END).setHeader(createToolItems());
|
||||
|
||||
grid.setMultiSort(true, Grid.MultiSortPriority.APPEND);
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private HorizontalLayout createAccountManagementButtons(ResponseAccount account) {
|
||||
var layout = new HorizontalLayout(JustifyContentMode.END);
|
||||
|
||||
{
|
||||
var button = new Button("Manage", VaadinIcon.COG_O.create());
|
||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
button.addClickListener(event -> {
|
||||
|
||||
});
|
||||
layout.add(button);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private HorizontalLayout createToolItems() {
|
||||
var layout = new HorizontalLayout(JustifyContentMode.END);
|
||||
|
||||
layout.add(createRegisterAccountButton());
|
||||
layout.add(createRefreshButton());
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Button createRegisterAccountButton() {
|
||||
var button = new Button("Register account", VaadinIcon.PLUS.create());
|
||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||
button.addClickListener(event -> openAccountRegistrationDialog());
|
||||
return button;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
var list = new ArrayList<ResponseAccount>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
var acc = new ResponseAccount("test" + i, "", Set.of(), false);
|
||||
list.add(acc);
|
||||
}
|
||||
|
||||
cachedAccounts = list; // TODO: accountRepository.getAllAccounts();
|
||||
applySearch(searchField.getValue());
|
||||
}
|
||||
|
||||
public void applySearch(String input) {
|
||||
var temp = input.trim();
|
||||
|
||||
grid.setItems(cachedAccounts.stream()
|
||||
.filter(account -> account.getUsername().startsWith(temp))
|
||||
.toList());
|
||||
}
|
||||
|
||||
private void openAccountRegistrationDialog() {
|
||||
var dialog = new Dialog();
|
||||
dialog.setHeaderTitle("Register new account");
|
||||
|
||||
var closeButton = new Button(LumoIcon.CROSS.create(), e -> dialog.close());
|
||||
closeButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||
dialog.getHeader().add(closeButton);
|
||||
|
||||
var layout = new VerticalLayout();
|
||||
|
||||
var fieldUsername = new TextField("Account username");
|
||||
fieldUsername.setWidth(70, Unit.PERCENTAGE);
|
||||
layout.add(fieldUsername);
|
||||
|
||||
var fieldPassword = new PasswordField("Password");
|
||||
fieldPassword.setWidth(70, Unit.PERCENTAGE);
|
||||
layout.add(fieldPassword);
|
||||
|
||||
var fieldConfirmPassword = new PasswordField("Confirm password");
|
||||
fieldConfirmPassword.setWidth(70, Unit.PERCENTAGE);
|
||||
layout.add(fieldConfirmPassword);
|
||||
|
||||
layout.add(new H3("Permissions"));
|
||||
|
||||
var permissionsList = new ArrayList<PermissionCheckBox>();
|
||||
for (var permission: Permission.Enum.values()) {
|
||||
var comp = new PermissionCheckBox(permission);
|
||||
permissionsList.add(comp);
|
||||
layout.add(comp);
|
||||
}
|
||||
|
||||
{
|
||||
var button = new Button("Register");
|
||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
button.setWidth(100, Unit.PERCENTAGE);
|
||||
button.addClickListener(event -> {
|
||||
validateAndRegister(dialog, fieldUsername, fieldPassword, fieldConfirmPassword, permissionsList);
|
||||
});
|
||||
dialog.getFooter().add(button);
|
||||
}
|
||||
|
||||
dialog.add(layout);
|
||||
dialog.setMinWidth(50, Unit.PERCENTAGE);
|
||||
dialog.setCloseOnEsc(true);
|
||||
dialog.setCloseOnOutsideClick(true);
|
||||
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
private void validateAndRegister(Dialog dialog, TextField username, PasswordField passwordField, PasswordField confirm, List<PermissionCheckBox> permissionCheckBoxes) {
|
||||
// TODO: validate and send request
|
||||
|
||||
dialog.close();
|
||||
refresh();
|
||||
}
|
||||
|
||||
private static class PermissionCheckBox extends Checkbox {
|
||||
|
||||
private final Permission.Enum option;
|
||||
|
||||
public PermissionCheckBox(Permission.Enum option) {
|
||||
super(option.getDescription());
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public Permission.Enum getOption() {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package ru.dragonestia.picker.cp.model;
|
||||
|
||||
import com.github.javaparser.quality.NotNull;
|
||||
import lombok.Getter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class Permission implements GrantedAuthority {
|
||||
@ -15,4 +16,19 @@ public class Permission implements GrantedAuthority {
|
||||
public String getAuthority() {
|
||||
return authority;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum Enum {
|
||||
// All from ru.dragonestia.picker.model.Permission (server)
|
||||
// Except for USER and ADMIN
|
||||
|
||||
NODE_MANAGEMENT("Create and remove nodes"),
|
||||
;
|
||||
|
||||
private final String description;
|
||||
|
||||
Enum(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package ru.dragonestia.picker.cp.page;
|
||||
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import ru.dragonestia.picker.api.repository.AccountRepository;
|
||||
import ru.dragonestia.picker.cp.component.AccountList;
|
||||
import ru.dragonestia.picker.cp.service.SecurityService;
|
||||
|
||||
@RolesAllowed("ADMIN")
|
||||
@PageTitle("Accounts")
|
||||
@Route(value = "/admin/accounts", layout = MainLayout.class)
|
||||
@RequiredArgsConstructor
|
||||
public class AccountsPage extends VerticalLayout {
|
||||
|
||||
private final AccountRepository accountRepository;
|
||||
|
||||
@Autowired
|
||||
public AccountsPage(SecurityService securityService) {
|
||||
accountRepository = securityService.getAuthenticatedAccount().getClient().getAccountRepository();
|
||||
|
||||
add(new H2("Account management"));
|
||||
add(new AccountList(accountRepository));
|
||||
}
|
||||
}
|
||||
@ -74,6 +74,9 @@ public class MainLayout extends AppLayout {
|
||||
var nav = new SideNav();
|
||||
nav.addItem(new SideNavItem("Nodes list", NodesPage.class, VaadinIcon.FOLDER_O.create()));
|
||||
nav.addItem(new SideNavItem("Search users", UserSearchPage.class, VaadinIcon.SEARCH.create()));
|
||||
if (isAdmin) {
|
||||
nav.addItem(new SideNavItem("Accounts", AccountsPage.class, VaadinIcon.USERS.create()));
|
||||
}
|
||||
nav.addItem(new SideNavItem("Documentation", "https://github.com/ScarletRedMan/RoomPicker", VaadinIcon.BOOK.create()));
|
||||
nav.addItem(new SideNavItem("Swagger UI", serverUrl + "/api-docs-ui", VaadinIcon.CURLY_BRACKETS.create()));
|
||||
return nav;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user