package service.ui; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; import com.vaadin.annotations.VaadinServletConfiguration; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.data.util.converter.Converter; import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutListener; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinServlet; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.spring.annotation.SpringUI; import com.vaadin.ui.*; import com.vaadin.ui.renderers.HtmlRenderer; import org.springframework.beans.factory.annotation.Autowired; import service.clients.MovieClient; import service.clients.RatingClient; import service.clients.UserClient; import service.models.Genre; import service.models.Movie; import service.models.Product; import service.models.User; import javax.servlet.annotation.WebServlet; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.stream.Collectors; @SpringUI(path = "/users") @Title("Users") @Theme("valo") public class UserUI extends UI { private static final long serialVersionUID = -3540851800967573466L; TextField filter = new TextField(); Grid items = new Grid(); Grid ratings = new Grid(); @Autowired MovieClient movieClient; @Autowired UserClient userClient; @Autowired RatingClient ratingClient; @Override protected void init(VaadinRequest request) { configureComponents(); buildLayout(); } private void configureComponents() { items.setContainerDataSource(new BeanItemContainer<>(User.class, userClient.findAll().getContent())); items.setColumnOrder("age", "gender", "occupation", "zipcode"); items.removeColumn("id"); ratings.setContainerDataSource(new BeanItemContainer<>(Movie.class)); ratings.setColumnOrder("id", "title", "genres", "url"); ratings.removeColumn("knownId"); ratings.removeColumn("id"); filter.addShortcutListener(new ShortcutListener("Press enter to submit...", ShortcutAction.KeyCode.ENTER, null) { @Override public void handleAction(Object sender, Object target) { refreshUsers(filter.getValue()); } }); items.setSelectionMode(Grid.SelectionMode.SINGLE); items.addSelectionListener(e -> { populateMovies(((User) items.getSelectedRow()).getId()); }); ratings.getColumn("genres").setRenderer(new HtmlRenderer(), new Converter<String, Genre[]>() { @Override public Genre[] convertToModel(String value, Class<? extends Genre[]> targetType, Locale locale) throws ConversionException { return null; } @Override public String convertToPresentation(Genre[] value, Class<? extends String> targetType, Locale locale) throws ConversionException { StringBuilder sb = new StringBuilder(); Arrays.asList(value).forEach(a -> sb.append("<span class=\"v-label v-widget v-panel\" style=\"margin: -4px 0.5em 0px; color: gray; padding: 0.25em; display: inline-block; font-size: 0.75em; font-weight: 300;\">").append(a.getName()).append("</span>")); return sb.toString(); } @Override public Class<Genre[]> getModelType() { return Genre[].class; } @Override public Class<String> getPresentationType() { return String.class; } }); // Set the custom link renderer for movies ratings.getColumn("url").setRenderer(new HtmlRenderer(), new Converter<String, String>() { @Override public String convertToModel(String value, Class<? extends String> targetType, Locale locale) throws ConversionException { return "not implemented"; } @Override public String convertToPresentation(String value, Class<? extends String> targetType, Locale locale) throws ConversionException { return "<a href='" + value + "' target='_blank'>" + value + "</a>"; } @Override public Class<String> getModelType() { return String.class; } @Override public Class<String> getPresentationType() { return String.class; } }); refreshUsers(); } /** * Populates the grid of movie records that the user has reviewed * * @param userId is the ID record of the user */ private void populateMovies(Long userId) { // Get the movies that this user has rated List<Product> productList = ratingClient.findProductsByUser(userId.toString()) .getContent() .stream() .collect(Collectors.toList()); // Translate those records to movie records ratings.setContainerDataSource(new BeanItemContainer<>(Movie.class, movieClient.findByIds(productList.stream().map(a -> a.getKnownId()).collect(Collectors.joining(","))).getContent())); } private void buildLayout() { VerticalLayout left = new VerticalLayout(items); left.setSizeFull(); items.setSizeFull(); left.setExpandRatio(items, 1); ratings.setHeightMode(HeightMode.CSS); ratings.setHeight("100%"); HorizontalLayout mainLayout = new HorizontalLayout(left, ratings); mainLayout.setSizeFull(); mainLayout.setExpandRatio(left, 1); setContent(mainLayout); } void refreshUsers() { refreshUsers(filter.getValue()); } private void refreshUsers(String stringFilter) { if (!Objects.equals(stringFilter.trim(), "")) { items.setContainerDataSource(new BeanItemContainer<>(User.class, userClient.findAll().getContent())); } } @WebServlet(urlPatterns = "/users") @VaadinServletConfiguration(ui = UserUI.class, productionMode = false) public static class UsersServlet extends VaadinServlet { } }