Implemented user details page

This commit is contained in:
Andrey Terentev 2024-02-05 13:57:07 +07:00 committed by Andrey Terentev
parent be203ccf5c
commit 3b8fa87c5b
19 changed files with 331 additions and 62 deletions

View File

@ -3,12 +3,14 @@ package ru.dragonestia.picker.api.repository;
import ru.dragonestia.picker.api.exception.NodeNotFoundException; import ru.dragonestia.picker.api.exception.NodeNotFoundException;
import ru.dragonestia.picker.api.exception.RoomAreFullException; import ru.dragonestia.picker.api.exception.RoomAreFullException;
import ru.dragonestia.picker.api.exception.RoomNotFoundException; import ru.dragonestia.picker.api.exception.RoomNotFoundException;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.response.type.RRoom; import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser; import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.api.repository.details.UserDetails; import ru.dragonestia.picker.api.repository.details.UserDetails;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
public interface UserRepository { public interface UserRepository {
@ -26,4 +28,8 @@ public interface UserRepository {
List<RUser> all(RRoom room, Set<UserDetails> details) throws NodeNotFoundException, RoomNotFoundException; List<RUser> all(RRoom room, Set<UserDetails> details) throws NodeNotFoundException, RoomNotFoundException;
List<RUser> search(String input, Set<UserDetails> details); List<RUser> search(String input, Set<UserDetails> details);
RUser find(String userId, Set<UserDetails> details);
List<RRoom.Short> getLinkedRoomsWithUsers(RUser user, Set<RoomDetails> roomDetails);
} }

View File

@ -0,0 +1,7 @@
package ru.dragonestia.picker.api.repository.response;
import ru.dragonestia.picker.api.repository.response.type.RRoom;
import java.util.List;
public record LinkedRoomsWithUserResponse(List<RRoom.Short> rooms) {}

View File

@ -0,0 +1,5 @@
package ru.dragonestia.picker.api.repository.response;
import ru.dragonestia.picker.api.repository.response.type.RUser;
public record UserDetailsResponse(RUser user) {}

View File

@ -87,5 +87,5 @@ public class RRoom {
return false; return false;
} }
public record Short(String id, int slots, boolean locked, Map<RoomDetails, String> details) {} public record Short(String id, String nodeId, int slots, boolean locked, Map<RoomDetails, String> details) {}
} }

View File

@ -1,16 +1,17 @@
package ru.dragonestia.picker.controller; package ru.dragonestia.picker.controller;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping; import ru.dragonestia.picker.api.repository.response.LinkedRoomsWithUserResponse;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.api.repository.response.SearchUserResponse; import ru.dragonestia.picker.api.repository.response.SearchUserResponse;
import ru.dragonestia.picker.api.repository.response.UserDetailsResponse;
import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.service.UserService; import ru.dragonestia.picker.service.UserService;
import ru.dragonestia.picker.util.DetailsParser;
import ru.dragonestia.picker.util.NamingValidator; import ru.dragonestia.picker.util.NamingValidator;
import java.util.HashSet;
import java.util.List; import java.util.List;
@RequiredArgsConstructor @RequiredArgsConstructor
@ -19,6 +20,7 @@ import java.util.List;
public class UserController { public class UserController {
private final UserService userService; private final UserService userService;
private final DetailsParser detailsParser;
private final NamingValidator namingValidator; private final NamingValidator namingValidator;
@GetMapping("/search") @GetMapping("/search")
@ -29,13 +31,28 @@ public class UserController {
return new SearchUserResponse(List.of()); return new SearchUserResponse(List.of());
} }
var details = new HashSet<UserDetails>(); return new SearchUserResponse(userService.searchUsers(input, detailsParser.parseUserDetails(detailsSeq)));
for (var detailStr: detailsSeq.split(",")) {
try {
details.add(UserDetails.valueOf(detailStr.toUpperCase()));
} catch (IllegalArgumentException ignore) {}
} }
return new SearchUserResponse(userService.searchUsers(input, details)); @GetMapping("/{userId}")
UserDetailsResponse find(@PathVariable(value = "userId") String userId,
@RequestParam(value = "requiredDetails", required = false) String detailsSeq) {
if (!namingValidator.validateUserId(userId)) {
return new UserDetailsResponse(new RUser(userId));
}
return new UserDetailsResponse(userService.getUserDetails(userId, detailsParser.parseUserDetails(detailsSeq)));
}
@GetMapping("/{userId}/rooms")
LinkedRoomsWithUserResponse roomsOf(@PathVariable(value = "userId") String userId,
@RequestParam(value = "requiredDetails", required = false) String detailsSeq) {
if (!namingValidator.validateUserId(userId)) {
return new LinkedRoomsWithUserResponse(List.of());
}
return new LinkedRoomsWithUserResponse(userService.getUserRoomsWithDetails(new User(userId), detailsParser.parseRoomDetails(detailsSeq)));
} }
} }

View File

@ -54,6 +54,6 @@ public class Room {
} }
public RRoom.Short toShortResponseObject() { public RRoom.Short toShortResponseObject() {
return new RRoom.Short(id, slots.getSlots(), locked, new HashMap<>()); return new RRoom.Short(id, nodeId, slots.getSlots(), locked, new HashMap<>());
} }
} }

View File

@ -1,7 +1,6 @@
package ru.dragonestia.picker.repository; package ru.dragonestia.picker.repository;
import ru.dragonestia.picker.api.exception.RoomAreFullException; import ru.dragonestia.picker.api.exception.RoomAreFullException;
import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;

View File

@ -1,6 +1,8 @@
package ru.dragonestia.picker.service; package ru.dragonestia.picker.service;
import ru.dragonestia.picker.api.exception.RoomAreFullException; import ru.dragonestia.picker.api.exception.RoomAreFullException;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser; import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.api.repository.details.UserDetails; import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Room;
@ -14,6 +16,8 @@ public interface UserService {
List<Room> getUserRooms(User user); List<Room> getUserRooms(User user);
List<RRoom.Short> getUserRoomsWithDetails(User user, Set<RoomDetails> details);
int linkUsersWithRoom(Room room, Collection<User> users, boolean force) throws RoomAreFullException; int linkUsersWithRoom(Room room, Collection<User> users, boolean force) throws RoomAreFullException;
void unlinkUsersFromRoom(Room room, Collection<User> users); void unlinkUsersFromRoom(Room room, Collection<User> users);
@ -23,4 +27,6 @@ public interface UserService {
List<RUser> getRoomUsersWithDetailsResponse(Room room, Set<UserDetails> details); List<RUser> getRoomUsersWithDetailsResponse(Room room, Set<UserDetails> details);
List<RUser> searchUsers(String input, Set<UserDetails> details); List<RUser> searchUsers(String input, Set<UserDetails> details);
RUser getUserDetails(String userId, Set<UserDetails> details);
} }

View File

@ -9,6 +9,7 @@ import ru.dragonestia.picker.api.repository.response.type.RNode;
import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.repository.NodeRepository; import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.service.NodeService; import ru.dragonestia.picker.service.NodeService;
import ru.dragonestia.picker.util.DetailsExtractor;
import ru.dragonestia.picker.util.NamingValidator; import ru.dragonestia.picker.util.NamingValidator;
import java.util.LinkedList; import java.util.LinkedList;
@ -21,6 +22,7 @@ import java.util.Set;
public class NodeServiceImpl implements NodeService { public class NodeServiceImpl implements NodeService {
private final NodeRepository nodeRepository; private final NodeRepository nodeRepository;
private final DetailsExtractor detailsExtractor;
private final NamingValidator namingValidator; private final NamingValidator namingValidator;
@Override @Override
@ -43,13 +45,7 @@ public class NodeServiceImpl implements NodeService {
public List<RNode> getAllNodesWithDetailsResponse(Set<NodeDetails> details) { public List<RNode> getAllNodesWithDetailsResponse(Set<NodeDetails> details) {
var response = new LinkedList<RNode>(); var response = new LinkedList<RNode>();
for (var node: all()) { for (var node: all()) {
var responseNode = node.toResponseObject(); response.add(detailsExtractor.extract(node, details));
for (var detail: details) {
// TODO...
}
response.add(responseNode);
} }
return response; return response;
} }

View File

@ -6,14 +6,13 @@ import org.springframework.stereotype.Service;
import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException; import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException; import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.api.repository.details.RoomDetails; import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.api.repository.response.type.RRoom; import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.service.RoomService; import ru.dragonestia.picker.service.RoomService;
import ru.dragonestia.picker.util.DetailsExtractor;
import ru.dragonestia.picker.util.NamingValidator; import ru.dragonestia.picker.util.NamingValidator;
import java.util.LinkedList; import java.util.LinkedList;
@ -27,7 +26,7 @@ import java.util.Set;
public class RoomServiceImpl implements RoomService { public class RoomServiceImpl implements RoomService {
private final RoomRepository roomRepository; private final RoomRepository roomRepository;
private final UserRepository userRepository; private final DetailsExtractor detailsExtractor;
private final NamingValidator namingValidator; private final NamingValidator namingValidator;
@Override @Override
@ -55,16 +54,7 @@ public class RoomServiceImpl implements RoomService {
public List<RRoom.Short> getAllRoomsWithDetailsResponse(Node node, Set<RoomDetails> details) { public List<RRoom.Short> getAllRoomsWithDetailsResponse(Node node, Set<RoomDetails> details) {
var response = new LinkedList<RRoom.Short>(); var response = new LinkedList<RRoom.Short>();
for (var room: all(node)) { for (var room: all(node)) {
var responseRoom = room.toShortResponseObject(); response.add(detailsExtractor.extract(room, details));
for (var detail: details) {
if (detail == RoomDetails.COUNT_USERS) {
var users = Integer.toString(userRepository.usersOf(room).size());
responseRoom.details().put(RoomDetails.COUNT_USERS, users);
}
}
response.add(responseRoom);
} }
return response; return response;
} }

View File

@ -2,12 +2,15 @@ package ru.dragonestia.picker.service.impl;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser; import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.api.repository.details.UserDetails; import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.UserRepository; import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.service.UserService; import ru.dragonestia.picker.service.UserService;
import ru.dragonestia.picker.util.DetailsExtractor;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@ -17,6 +20,7 @@ import java.util.function.Function;
public class UserServiceImpl implements UserService { public class UserServiceImpl implements UserService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final DetailsExtractor detailsExtractor;
private final Map<UserDetails, Function<User, String>> detailsMap = new HashMap<>(); private final Map<UserDetails, Function<User, String>> detailsMap = new HashMap<>();
@Override @Override
@ -24,6 +28,15 @@ public class UserServiceImpl implements UserService {
return userRepository.findAllLinkedUserRooms(user); return userRepository.findAllLinkedUserRooms(user);
} }
@Override
public List<RRoom.Short> getUserRoomsWithDetails(User user, Set<RoomDetails> details) {
var result = new LinkedList<RRoom.Short>();
for (var room: getUserRooms(user)) {
result.add(detailsExtractor.extract(room, details));
}
return result;
}
@Override @Override
public int linkUsersWithRoom(Room room, Collection<User> users, boolean force) { public int linkUsersWithRoom(Room room, Collection<User> users, boolean force) {
userRepository.linkWithRoom(room, users, force); userRepository.linkWithRoom(room, users, force);
@ -44,32 +57,18 @@ public class UserServiceImpl implements UserService {
public List<RUser> getRoomUsersWithDetailsResponse(Room room, Set<UserDetails> details) { public List<RUser> getRoomUsersWithDetailsResponse(Room room, Set<UserDetails> details) {
var users = new LinkedList<RUser>(); var users = new LinkedList<RUser>();
for (var user: getRoomUsers(room)) { for (var user: getRoomUsers(room)) {
var responseUser = user.toResponseObject(); users.add(detailsExtractor.extract(user, details));
for (var detail: details) {
if (detail == UserDetails.COUNT_ROOMS) {
responseUser.putDetail(UserDetails.COUNT_ROOMS, Integer.toString(getUserRooms(user).size()));
}
}
users.add(responseUser);
} }
return users; return users;
} }
@Override @Override
public List<RUser> searchUsers(String input, Set<UserDetails> details) { public List<RUser> searchUsers(String input, Set<UserDetails> details) {
return userRepository.search(input).stream() return userRepository.search(input).stream().map(user -> detailsExtractor.extract(user, details)).toList();
.map(user -> {
var responseUser = user.toResponseObject();
for (var detail: details) {
if (detail == UserDetails.COUNT_ROOMS) {
responseUser.putDetail(UserDetails.COUNT_ROOMS, Integer.toString(getUserRooms(user).size()));
}
} }
return responseUser; @Override
}).toList(); public RUser getUserDetails(String userId, Set<UserDetails> details) {
return detailsExtractor.extract(new User(userId), details);
} }
} }

View File

@ -0,0 +1,62 @@
package ru.dragonestia.picker.util;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.repository.details.NodeDetails;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.api.repository.response.type.RNode;
import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import java.util.Set;
@RequiredArgsConstructor
@Component
public class DetailsExtractor {
private final NodeRepository nodeRepository;
private final RoomRepository roomRepository;
private final UserRepository userRepository;
public RNode extract(Node node, Set<NodeDetails> details) {
var response = node.toResponseObject();
for (var detail: details) {
// TODO...
}
return response;
}
public RRoom.Short extract(Room room, Set<RoomDetails> details) {
var response = room.toShortResponseObject();
for (var detail: details) {
if (detail == RoomDetails.COUNT_USERS) {
var users = Integer.toString(userRepository.usersOf(room).size());
response.details().put(RoomDetails.COUNT_USERS, users);
}
}
return response;
}
public RUser extract(User user, Set<UserDetails> details) {
var response = user.toResponseObject();
for (var detail: details) {
if (detail == UserDetails.COUNT_ROOMS) {
response.putDetail(UserDetails.COUNT_ROOMS, Integer.toString(userRepository.findAllLinkedUserRooms(user).size()));
}
}
return response;
}
}

View File

@ -0,0 +1,43 @@
package ru.dragonestia.picker.util;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.repository.details.NodeDetails;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.details.UserDetails;
import java.util.HashSet;
import java.util.Set;
@Component
public class DetailsParser {
public Set<NodeDetails> parseNodeDetails(String detailsSeq) {
var details = new HashSet<NodeDetails>();
for (var detailStr: detailsSeq.split(",")) {
try {
details.add(NodeDetails.valueOf(detailStr.toUpperCase()));
} catch (IllegalArgumentException ignore) {}
}
return details;
}
public Set<RoomDetails> parseRoomDetails(String detailsSeq) {
var details = new HashSet<RoomDetails>();
for (var detailStr: detailsSeq.split(",")) {
try {
details.add(RoomDetails.valueOf(detailStr.toUpperCase()));
} catch (IllegalArgumentException ignore) {}
}
return details;
}
public Set<UserDetails> parseUserDetails(String detailsSeq) {
var details = new HashSet<UserDetails>();
for (var detailStr: detailsSeq.split(",")) {
try {
details.add(UserDetails.valueOf(detailStr.toUpperCase()));
} catch (IllegalArgumentException ignore) {}
}
return details;
}
}

View File

@ -1,5 +1,7 @@
package ru.dragonestia.picker.cp.component; package ru.dragonestia.picker.cp.component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.grid.ColumnTextAlign; import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.html.Span;
@ -32,10 +34,19 @@ public class UserList extends VerticalLayout {
grid.addColumn(RUser::getId).setHeader("User Identifier").setFooter(totalUsers); grid.addColumn(RUser::getId).setHeader("User Identifier").setFooter(totalUsers);
grid.addColumn(user -> user.getDetail(UserDetails.COUNT_ROOMS)).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with rooms") grid.addColumn(user -> user.getDetail(UserDetails.COUNT_ROOMS)).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with rooms")
.setFooter(occupancy); .setFooter(occupancy);
grid.addComponentColumn(user -> new Span("buttons")).setHeader("Manage"); // TODO grid.addComponentColumn(this::createManageButton).setHeader("Manage");
return grid; return grid;
} }
private Button createManageButton(RUser user) {
var button = new Button("Details");
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(e -> {
getUI().ifPresent(ui -> ui.navigate("/users/" + user.getId()));
});
return button;
}
public void update(List<RUser> users) { public void update(List<RUser> users) {
cachedUsers = users; cachedUsers = users;
usersGrid.setItems(users); usersGrid.setItems(users);

View File

@ -1,17 +1,29 @@
package ru.dragonestia.picker.cp.page; package ru.dragonestia.picker.cp.page;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H1; import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Paragraph; import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.notification.Notification;
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.router.*; import com.vaadin.flow.router.*;
import java.awt.*;
@Route(value = "/", layout = MainLayout.class) @Route(value = "/", layout = MainLayout.class)
public class HomePage extends VerticalLayout { public class HomePage extends VerticalLayout {
public HomePage() { public HomePage() {
super(); super();
add(new H1("Hello world!")); var field = new TextField("Some field");
add(new Paragraph("Hello world!")); field.setRequired(true);
add(field);
var button = new Button("Click me", e -> {
Notification.show(field.isInvalid() + "");
});
add(button);
} }
} }

View File

@ -0,0 +1,74 @@
package ru.dragonestia.picker.cp.page;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Span;
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.RequiredArgsConstructor;
import ru.dragonestia.picker.api.repository.RoomRepository;
import ru.dragonestia.picker.api.repository.UserRepository;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.cp.util.RouteParamsExtractor;
import java.util.LinkedList;
import java.util.List;
@RequiredArgsConstructor
@PageTitle("User details")
@Route(value = "/users/:userId", layout = MainLayout.class)
public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserver {
private final UserRepository userRepository;
private final RouteParamsExtractor paramsExtractor;
private RUser user;
private Grid<RRoom.Short> gridRooms;
private List<RRoom.Short> cachedRooms = new LinkedList<>();
@Override
public void beforeEnter(BeforeEnterEvent event) {
user = paramsExtractor.extractUserId(event);
init();
}
private void init() {
add(new H2("User '%s'".formatted(user.getId())));
add(new H3("Linked with rooms"));
add(gridRooms = createGrid());
update(userRepository.getLinkedRoomsWithUsers(user, RoomRepository.ALL_DETAILS));
}
private Grid<RRoom.Short> createGrid() {
var grid = new Grid<RRoom.Short>();
grid.addColumn(RRoom.Short::id).setHeader("Room identifier");
grid.addColumn(RRoom.Short::nodeId).setHeader("Node identifier");
grid.addColumn(room -> room.details().get(RoomDetails.COUNT_USERS)).setHeader("Users");
grid.addComponentColumn(room -> {
var button = new Button("Details");
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> {
getUI().ifPresent(ui -> ui.navigate("/nodes/%s/rooms/%s".formatted(room.nodeId(), room.id())));
});
return button;
}).setHeader("Other");
return grid;
}
public void update(List<RRoom.Short> rooms) {
gridRooms.setItems(cachedRooms = rooms);
}
}

View File

@ -1,5 +1,6 @@
package ru.dragonestia.picker.cp.page; package ru.dragonestia.picker.cp.page;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.Unit; import com.vaadin.flow.component.Unit;
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;
@ -49,6 +50,7 @@ public class UserSearchPage extends VerticalLayout {
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.getStyle().set("color", "#FFFFFF"); button.getStyle().set("color", "#FFFFFF");
button.addClickListener(event -> search(fieldUsername.getValue().trim())); button.addClickListener(event -> search(fieldUsername.getValue().trim()));
button.addClickShortcut(Key.ENTER);
field.setSuffixComponent(button); field.setSuffixComponent(button);
return field; return field;
@ -62,7 +64,14 @@ public class UserSearchPage extends VerticalLayout {
grid.addColumn(user -> user.getDetail(UserDetails.COUNT_ROOMS)).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with rooms"); grid.addColumn(user -> user.getDetail(UserDetails.COUNT_ROOMS)).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with rooms");
grid.addComponentColumn(user -> new Span("buttons")).setHeader("Manage"); // TODO grid.addComponentColumn(user -> {
var button = new Button("Details");
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> {
getUI().ifPresent(ui -> ui.navigate("/users/" + user.getId()));
});
return button;
}).setHeader("Manage");
return grid; return grid;
} }

View File

@ -7,16 +7,17 @@ import org.springframework.http.HttpMethod;
import ru.dragonestia.picker.api.exception.NodeNotFoundException; import ru.dragonestia.picker.api.exception.NodeNotFoundException;
import ru.dragonestia.picker.api.exception.RoomAreFullException; import ru.dragonestia.picker.api.exception.RoomAreFullException;
import ru.dragonestia.picker.api.exception.RoomNotFoundException; import ru.dragonestia.picker.api.exception.RoomNotFoundException;
import ru.dragonestia.picker.api.repository.details.RoomDetails;
import ru.dragonestia.picker.api.repository.response.LinkedRoomsWithUserResponse;
import ru.dragonestia.picker.api.repository.response.SearchUserResponse; import ru.dragonestia.picker.api.repository.response.SearchUserResponse;
import ru.dragonestia.picker.api.repository.response.UserDetailsResponse;
import ru.dragonestia.picker.api.repository.response.type.RRoom; import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.response.type.RUser; import ru.dragonestia.picker.api.repository.response.type.RUser;
import ru.dragonestia.picker.api.repository.UserRepository; import ru.dragonestia.picker.api.repository.UserRepository;
import ru.dragonestia.picker.api.repository.details.UserDetails; import ru.dragonestia.picker.api.repository.details.UserDetails;
import ru.dragonestia.picker.api.repository.response.RoomUserListResponse; import ru.dragonestia.picker.api.repository.response.RoomUserListResponse;
import java.util.Collection; import java.util.*;
import java.util.List;
import java.util.Set;
@Log4j2 @Log4j2
@RequiredArgsConstructor @RequiredArgsConstructor
@ -68,4 +69,28 @@ public class UserRepositoryImpl implements UserRepository {
params.put("input", input); params.put("input", input);
}).users(); }).users();
} }
@Override
public RUser find(String userId, Set<UserDetails> details) {
return rest.query("/users/" + userId,
HttpMethod.GET,
UserDetailsResponse.class,
params -> {
var detailsStr = String.join(",", details.stream().map(Enum::toString).toList());
params.put("requiredDetails", detailsStr);
}).user();
}
@Override
public List<RRoom.Short> getLinkedRoomsWithUsers(RUser user, Set<RoomDetails> details) {
return rest.query("/users/" + user.getId() + "/rooms",
HttpMethod.GET,
LinkedRoomsWithUserResponse.class,
params -> {
var detailsStr = String.join(",", details.stream().map(Enum::toString).toList());
params.put("requiredDetails", detailsStr);
}).rooms(); // TODO
}
} }

View File

@ -5,10 +5,12 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NodeNotFoundException; import ru.dragonestia.picker.api.exception.NodeNotFoundException;
import ru.dragonestia.picker.api.exception.RoomNotFoundException; import ru.dragonestia.picker.api.exception.RoomNotFoundException;
import ru.dragonestia.picker.api.repository.UserRepository;
import ru.dragonestia.picker.api.repository.response.type.RNode; import ru.dragonestia.picker.api.repository.response.type.RNode;
import ru.dragonestia.picker.api.repository.response.type.RRoom; import ru.dragonestia.picker.api.repository.response.type.RRoom;
import ru.dragonestia.picker.api.repository.NodeRepository; import ru.dragonestia.picker.api.repository.NodeRepository;
import ru.dragonestia.picker.api.repository.RoomRepository; import ru.dragonestia.picker.api.repository.RoomRepository;
import ru.dragonestia.picker.api.repository.response.type.RUser;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
@ -16,6 +18,7 @@ public class RouteParamsExtractor {
private final NodeRepository nodeRepository; private final NodeRepository nodeRepository;
private final RoomRepository roomRepository; private final RoomRepository roomRepository;
private final UserRepository userRepository;
public RNode extractNodeId(BeforeEnterEvent e) throws NodeNotFoundException { public RNode extractNodeId(BeforeEnterEvent e) throws NodeNotFoundException {
var nodeId = e.getRouteParameters().get("nodeId").orElseThrow(() -> new NodeNotFoundException("null")); var nodeId = e.getRouteParameters().get("nodeId").orElseThrow(() -> new NodeNotFoundException("null"));
@ -26,4 +29,9 @@ public class RouteParamsExtractor {
var roomId = e.getRouteParameters().get("roomId").orElseThrow(() -> new NodeNotFoundException("null")); var roomId = e.getRouteParameters().get("roomId").orElseThrow(() -> new NodeNotFoundException("null"));
return roomRepository.find(node, roomId).orElseThrow(() -> new NodeNotFoundException(roomId)); return roomRepository.find(node, roomId).orElseThrow(() -> new NodeNotFoundException(roomId));
} }
public RUser extractUserId(BeforeEnterEvent e) {
var userId = e.getRouteParameters().get("userId").orElseThrow(RuntimeException::new);
return userRepository.find(userId, UserRepository.ALL_DETAILS);
}
} }