| @ -1,18 +0,0 @@ | |||
| package app.components.leafletmap; | |||
| import com.vaadin.flow.component.Component; | |||
| import com.vaadin.flow.component.HasSize; | |||
| import com.vaadin.flow.component.Tag; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dependency.JsModule; | |||
| @CssImport("leaflet/dist/leaflet.css") | |||
| @JsModule("app/components/leafletmap/leaflet-map.js") | |||
| @Tag("leaflet-map") | |||
| public class LeafletMap extends Component implements HasSize { | |||
| public void setView(double latitude, double longitude, int zoomLevel) { | |||
| getElement().callJsFunction("setView", latitude, longitude, zoomLevel); | |||
| } | |||
| } | |||
| @ -1,11 +1,11 @@ | |||
| package app.data; | |||
| package app.data.entity; | |||
| import javax.persistence.GeneratedValue; | |||
| import javax.persistence.Id; | |||
| import javax.persistence.MappedSuperclass; | |||
| @MappedSuperclass | |||
| public abstract class AbstractEntity { | |||
| public abstract class AbstractEntity { // TODO: Use this in your own entities (adapt annotations and equals()) | |||
| @Id | |||
| @GeneratedValue | |||
| @ -1,6 +1,6 @@ | |||
| package app.data.entity; | |||
| package app.data.entity.example; | |||
| import app.data.AbstractEntity; | |||
| import app.data.entity.AbstractEntity; | |||
| import javax.persistence.Entity; | |||
| @ -1,6 +1,6 @@ | |||
| package app.data.entity; | |||
| package app.data.entity.example; | |||
| import app.data.AbstractEntity; | |||
| import app.data.entity.AbstractEntity; | |||
| import javax.persistence.Entity; | |||
| import java.time.LocalDate; | |||
| @ -1,40 +0,0 @@ | |||
| package app.data.generator; | |||
| import app.data.service.SamplePersonRepository; | |||
| import com.vaadin.flow.spring.annotation.SpringComponent; | |||
| import org.springframework.boot.CommandLineRunner; | |||
| import org.springframework.context.annotation.Bean; | |||
| @SpringComponent | |||
| public class DataGenerator { | |||
| @Bean | |||
| public CommandLineRunner loadData(SamplePersonRepository samplePersonRepository) { | |||
| return args -> { | |||
| // Logger logger = LoggerFactory.getLogger(getClass()); | |||
| // if (samplePersonRepository.count() != 0L) { | |||
| // logger.info("Using existing database"); | |||
| // return; | |||
| // } | |||
| // int seed = 123; | |||
| // | |||
| // logger.info("Generating demo data"); | |||
| // | |||
| // logger.info("... generating 100 Sample Person entities..."); | |||
| // ExampleDataGenerator<SamplePerson> samplePersonRepositoryGenerator = new ExampleDataGenerator<>( | |||
| // SamplePerson.class, LocalDateTime.of(2021, 2, 26, 0, 0, 0)); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setId, DataType.ID); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setFirstName, DataType.FIRST_NAME); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setLastName, DataType.LAST_NAME); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setEmail, DataType.EMAIL); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setPhone, DataType.PHONE_NUMBER); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setDateOfBirth, DataType.DATE_OF_BIRTH); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setOccupation, DataType.OCCUPATION); | |||
| // samplePersonRepositoryGenerator.setData(SamplePerson::setImportant, DataType.BOOLEAN_10_90); | |||
| // samplePersonRepository.saveAll(samplePersonRepositoryGenerator.create(100, seed)); | |||
| // | |||
| // logger.info("Generated demo data"); | |||
| }; | |||
| } | |||
| } | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.GameInfo; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.Game; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.Match; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.Matchday; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.PlayerInfo; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.Player; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,4 +1,4 @@ | |||
| package app.data.service; | |||
| package app.data.repository; | |||
| import app.data.entity.Season; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| @ -1,6 +1,6 @@ | |||
| package app.data.service; | |||
| package app.data.repository.example; | |||
| import app.data.entity.SampleAddress; | |||
| import app.data.entity.example.SampleAddress; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| public interface SampleAddressRepository extends JpaRepository<SampleAddress, Integer> { | |||
| @ -1,6 +1,6 @@ | |||
| package app.data.service; | |||
| package app.data.repository.example; | |||
| import app.data.entity.SamplePerson; | |||
| import app.data.entity.example.SamplePerson; | |||
| import org.springframework.data.jpa.repository.JpaRepository; | |||
| public interface SamplePersonRepository extends JpaRepository<SamplePerson, Integer> { | |||
| @ -1,6 +1,7 @@ | |||
| package app.data.service; | |||
| package app.data.service.example; | |||
| import app.data.entity.SampleAddress; | |||
| import app.data.entity.example.SampleAddress; | |||
| import app.data.repository.example.SampleAddressRepository; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import org.vaadin.artur.helpers.CrudService; | |||
| @ -1,6 +1,7 @@ | |||
| package app.data.service; | |||
| package app.data.service.example; | |||
| import app.data.entity.SamplePerson; | |||
| import app.data.entity.example.SamplePerson; | |||
| import app.data.repository.example.SamplePersonRepository; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import org.vaadin.artur.helpers.CrudService; | |||
| @ -1,17 +1,17 @@ | |||
| package app.image; | |||
| package app.gameimage; | |||
| import javax.imageio.ImageIO; | |||
| import java.awt.image.BufferedImage; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| public class ImageUtils { | |||
| public class GameImageUtils { | |||
| public static final String IMAGE_SOURCE_PATH = "src/main/resources/META-INF/resources/images/chess-sources/"; | |||
| public static final String IMAGE_DEST_PATH = "src/main/resources/META-INF/resources/images/games/"; | |||
| public static final String EXTENSION = ".png"; | |||
| private static final String EXTENSION_WITHOUT_DOT = "png"; | |||
| private ImageUtils() {} | |||
| private GameImageUtils() {} | |||
| public static BufferedImage readImage(String fileNameWithoutExtension) { | |||
| BufferedImage img = null; | |||
| @ -1,4 +1,4 @@ | |||
| package app.components.navigation; | |||
| package app.navigation.components; | |||
| import app.navigation.Navigation; | |||
| import com.vaadin.flow.component.html.Label; | |||
| @ -1,4 +1,4 @@ | |||
| package app.components.navigation.button; | |||
| package app.navigation.components.button; | |||
| import app.navigation.Navigation; | |||
| @ -1,4 +1,4 @@ | |||
| package app.components.navigation.button; | |||
| package app.navigation.components.button; | |||
| import app.data.entity.Matchday; | |||
| import app.navigation.Navigation; | |||
| @ -1,4 +1,4 @@ | |||
| package app.components.navigation.button; | |||
| package app.navigation.components.button; | |||
| import app.data.entity.Matchday; | |||
| import app.navigation.Navigation; | |||
| @ -0,0 +1,28 @@ | |||
| package app.navigation.service; | |||
| import app.data.service.MatchService; | |||
| import app.data.service.MatchdayService; | |||
| import app.data.service.SeasonService; | |||
| import app.navigation.Navigation; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| @Service | |||
| public class NavigationService { | |||
| private final SeasonService seasonService; | |||
| private final MatchdayService matchdayService; | |||
| private final MatchService matchService; | |||
| public NavigationService(@Autowired SeasonService seasonService, | |||
| @Autowired MatchdayService matchdayService, | |||
| @Autowired MatchService matchService) { | |||
| this.seasonService = seasonService; | |||
| this.matchdayService = matchdayService; | |||
| this.matchService = matchService; | |||
| } | |||
| public Navigation getNewNavigation() { | |||
| return new Navigation(seasonService, matchdayService, matchService); | |||
| } | |||
| } | |||
| @ -1,22 +0,0 @@ | |||
| package app.views.example.map; | |||
| import app.components.leafletmap.LeafletMap; | |||
| import app.views.main.MainView; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| @Route(value = "map", layout = MainView.class) | |||
| @PageTitle("Map") | |||
| public class MapView extends VerticalLayout { | |||
| private LeafletMap map = new LeafletMap(); | |||
| public MapView() { | |||
| setSizeFull(); | |||
| setPadding(false); | |||
| map.setSizeFull(); | |||
| map.setView(55.0, 10.0, 4); | |||
| add(map); | |||
| } | |||
| } | |||
| @ -1,58 +1,54 @@ | |||
| package app.views.match; | |||
| import app.data.entity.Game; | |||
| import app.data.entity.Match; | |||
| import app.data.service.MatchService; | |||
| import app.data.service.MatchdayService; | |||
| import app.data.service.SeasonService; | |||
| import app.image.ImageService; | |||
| import app.navigation.Navigation; | |||
| import app.navigation.service.NavigationService; | |||
| import app.views.main.MainView; | |||
| import app.views.navigation.NavigationViewBase; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.html.Image; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @CssImport("app/views/match/match-view.css") | |||
| @Route(value = "match", layout = MainView.class) | |||
| @PageTitle("Schachliga DACH - Results - Matches") | |||
| public class MatchView extends NavigationViewBase { | |||
| private final List<Image> images = new ArrayList<>(); | |||
| private final MatchService matchService; | |||
| private final ImageService imageService; | |||
| public MatchView(@Autowired NavigationService navigationService, | |||
| @Autowired MatchService matchService) { | |||
| super(navigationService, true, true, true); | |||
| this.matchService = matchService; | |||
| public MatchView(@Autowired SeasonService seasonService, | |||
| @Autowired MatchdayService matchdayService, | |||
| @Autowired MatchService matchService, | |||
| @Autowired ImageService imageService) { | |||
| super(seasonService, matchdayService, matchService, true, true, true); | |||
| this.imageService = imageService; | |||
| addClassName("match-view"); | |||
| this.navigation.setSeasonEnabled(true); | |||
| this.navigation.setMatchdayEnabled(true); | |||
| this.navigation.setMatchEnabled(true); | |||
| configureLayout(); | |||
| } | |||
| /////////// | |||
| // ROUTE // | |||
| /////////// | |||
| @Override | |||
| public String getRoute() { | |||
| return "match"; | |||
| } | |||
| //////////// | |||
| // LAYOUT // | |||
| //////////// | |||
| private void configureLayout() { | |||
| } | |||
| ///////////// | |||
| // CONTENT // | |||
| ///////////// | |||
| @Override | |||
| protected void configureContent() { | |||
| Match match = navigation.getSelectedMatch().orElseThrow(); | |||
| removeAll(); | |||
| for (Game game : match.getGames()) { | |||
| Image image = new Image(imageService.getVaadinImagePath(game).orElse(""), "image"); | |||
| image.setWidth("30%"); | |||
| add(image); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,96 @@ | |||
| package app.views.matchday.components; | |||
| import app.data.bean.CalculatedMatch; | |||
| import app.data.entity.Matchday; | |||
| import app.navigation.Navigation; | |||
| import app.navigation.components.button.NextMatchdayButton; | |||
| import app.navigation.components.button.PrevMatchdayButton; | |||
| import app.utils.StringUtils; | |||
| import app.utils.VaadinUtils; | |||
| import app.views.navigation.interfaces.ContentConfigurable; | |||
| import com.vaadin.flow.component.grid.ColumnTextAlign; | |||
| import com.vaadin.flow.component.grid.Grid; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.html.Div; | |||
| import com.vaadin.flow.component.html.Label; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.function.ValueProvider; | |||
| import java.util.NoSuchElementException; | |||
| public class MatchdayComponent extends Div implements ContentConfigurable { | |||
| private final Navigation navigation; | |||
| private final VerticalLayout inner = new VerticalLayout(); | |||
| private final HorizontalLayout header = new HorizontalLayout(); | |||
| private final Label headerLabel = new Label(); | |||
| private final Grid<CalculatedMatch> grid = new Grid<>(); | |||
| public MatchdayComponent(Navigation navigation) { | |||
| this.navigation = navigation; | |||
| addClassName("wrapper"); | |||
| add(inner); | |||
| inner.add(header, grid); | |||
| configureHeader(); | |||
| configureGrid(); | |||
| } | |||
| private void configureHeader() { | |||
| header.add(new PrevMatchdayButton(this.navigation), headerLabel, new NextMatchdayButton(this.navigation)); | |||
| header.setWidthFull(); | |||
| headerLabel.addClassName("matchday-header-label"); | |||
| } | |||
| private void configureGrid() { | |||
| Label headerPlayer1 = new Label("Player 1"); | |||
| headerPlayer1.addClassName("column_header"); | |||
| Label headerPlayer2 = new Label("Player 2"); | |||
| headerPlayer2.addClassName("column_header"); | |||
| grid.addColumn(VaadinUtils.getPlayerRenderer(CalculatedMatch::getPlayer1)) | |||
| .setHeader(headerPlayer1) | |||
| .setTextAlign(ColumnTextAlign.END) | |||
| .setWidth("13em") | |||
| .setFlexGrow(1); | |||
| grid.addColumn((ValueProvider<CalculatedMatch, String>) this::getResultString) | |||
| .setHeader("vs.") | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("6em"); | |||
| grid.addColumn(VaadinUtils.getPlayerRenderer(CalculatedMatch::getPlayer2)) | |||
| .setHeader(headerPlayer2) | |||
| .setTextAlign(ColumnTextAlign.START) | |||
| .setWidth("13em") | |||
| .setFlexGrow(1); | |||
| grid.setWidth("32em"); // TODO: find a way to set this dynamically based on column widths | |||
| grid.setHeightByRows(true); | |||
| grid.addThemeVariants(GridVariant.LUMO_NO_BORDER, | |||
| GridVariant.LUMO_NO_ROW_BORDERS, GridVariant.LUMO_ROW_STRIPES); | |||
| } | |||
| private String getResultString(CalculatedMatch match) { | |||
| return StringUtils.getResultString(match.getScore1(), match.getScore2()); | |||
| } | |||
| @Override | |||
| public void configureContent() { | |||
| try { | |||
| Matchday matchday = navigation.getSelectedMatchday().orElseThrow(); | |||
| headerLabel.setText(String.format("Matchday %s", matchday.toString())); // TODO: add dates | |||
| grid.setItems(navigation.getMatchService().getCalculatedMatches(matchday)); | |||
| } catch (NoSuchElementException e) { | |||
| removeAll(); | |||
| add(navigation.getValidationLabel()); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,5 @@ | |||
| package app.views.navigation.interfaces; | |||
| public interface ContentConfigurable { | |||
| void configureContent(); | |||
| } | |||
| @ -0,0 +1,129 @@ | |||
| package app.views.table.components; | |||
| import app.data.bean.PlayerForTable; | |||
| import app.data.entity.Matchday; | |||
| import app.data.service.PlayerService; | |||
| import app.navigation.Navigation; | |||
| import app.utils.StringUtils; | |||
| import app.utils.VaadinUtils; | |||
| import app.views.navigation.interfaces.ContentConfigurable; | |||
| import com.vaadin.flow.component.grid.ColumnTextAlign; | |||
| import com.vaadin.flow.component.grid.Grid; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.html.Div; | |||
| import com.vaadin.flow.component.html.Label; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import java.util.NoSuchElementException; | |||
| public class TableComponent extends Div implements ContentConfigurable { | |||
| private final Navigation navigation; | |||
| private final PlayerService playerService; | |||
| private final Grid<PlayerForTable> grid = new Grid<>(); | |||
| public TableComponent(Navigation navigation, @Autowired PlayerService playerService) { | |||
| this.navigation = navigation; | |||
| this.playerService = playerService; | |||
| addClassName("grid-wrapper"); | |||
| add(grid); | |||
| configureGrid(); | |||
| } | |||
| private void configureGrid() { | |||
| // TODO: add diff to last matchday | |||
| // TODO: rounded corners for rows? | |||
| Label headerPlace = new Label("Place"); | |||
| headerPlace.addClassName("important-table-column-header"); | |||
| Label headerPlayer = new Label("Player"); | |||
| headerPlayer.addClassName("important-table-column-header"); | |||
| Label headerMatchesPlayed = new Label("Played"); | |||
| Label headerMatchPoints = new Label("Points"); | |||
| headerMatchPoints.addClassName("important-table-column-header"); | |||
| Label headerWon = new Label("W"); | |||
| Label headerDrawn = new Label("D"); | |||
| Label headerLost = new Label("L"); | |||
| Label headerGames = new Label("Games"); | |||
| Label headerDiff = new Label("Diff"); | |||
| grid.addColumn(VaadinUtils.getBoldStringRenderer(PlayerForTable::getPlaceString)) | |||
| .setHeader(headerPlace) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| // .setClassNameGenerator(playerForTable -> "leftmost-column-cell") | |||
| .setWidth("5em"); | |||
| grid.addColumn(VaadinUtils.getPlayerRenderer(PlayerForTable::getPlayer)) | |||
| .setHeader(headerPlayer) | |||
| .setTextAlign(ColumnTextAlign.START) | |||
| .setWidth("13em"); | |||
| grid.addColumn(PlayerForTable::getAmountOfMatches) | |||
| .setHeader(headerMatchesPlayed) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("5em"); | |||
| grid.addColumn(VaadinUtils.getBoldStringRenderer(player -> String.valueOf(player.getMatchPoints()))) | |||
| .setHeader(headerMatchPoints) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("6em"); | |||
| grid.addColumn(PlayerForTable::getAmountOfMatchesWon) | |||
| .setHeader(headerWon) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("3em"); | |||
| grid.addColumn(PlayerForTable::getAmountOfMatchesDrawn) | |||
| .setHeader(headerDrawn) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("3em"); | |||
| grid.addColumn(PlayerForTable::getAmountOfMatchesLost) | |||
| .setHeader(headerLost) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("3em"); | |||
| grid.addColumn(this::getResultString) | |||
| .setHeader(headerGames) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("6em"); | |||
| grid.addColumn(player -> StringUtils.getSignedString(player.getGamePointDiff())) | |||
| .setHeader(headerDiff) | |||
| .setTextAlign(ColumnTextAlign.CENTER) | |||
| .setWidth("5em"); | |||
| grid.setWidth("51em"); | |||
| grid.setHeightByRows(true); | |||
| grid.addThemeVariants(GridVariant.LUMO_NO_BORDER, | |||
| GridVariant.LUMO_NO_ROW_BORDERS, GridVariant.LUMO_ROW_STRIPES); | |||
| } | |||
| private String getResultString(PlayerForTable player) { | |||
| return StringUtils.getResultString(player.getGamePointsForSelf(), player.getGamePointsForOpponents()); | |||
| } | |||
| @Override | |||
| public void configureContent() { | |||
| try { | |||
| Matchday matchday = navigation.getSelectedMatchday().orElseThrow(); | |||
| grid.setItems(playerService.getPlayersForTable(matchday)); | |||
| } catch (NoSuchElementException e) { | |||
| removeAll(); | |||
| add(navigation.getValidationLabel()); | |||
| } | |||
| } | |||
| } | |||