Browse Source

match view basic

master
GAM 4 years ago
parent
commit
92418ba9d6
14 changed files with 564 additions and 363 deletions
  1. +1
    -1
      db/db_init.sql
  2. +16
    -0
      src/main/java/com/example/application/components/navigation/SeasonAndMatchdayNavigation.java
  3. +5
    -0
      src/main/java/com/example/application/data/entity/Match.java
  4. +15
    -1
      src/main/java/com/example/application/data/service/MatchService.java
  5. +7
    -7
      src/main/java/com/example/application/data/service/MatchdayService.java
  6. +1
    -1
      src/main/java/com/example/application/data/service/PlayerService.java
  7. +422
    -0
      src/main/java/com/example/application/navigation/Navigation.java
  8. +39
    -0
      src/main/java/com/example/application/navigation/NavigationUtils.java
  9. +7
    -0
      src/main/java/com/example/application/navigation/UrlParameterType.java
  10. +0
    -258
      src/main/java/com/example/application/views/abstractnavigation/SeasonAndMatchdayNavigation.java
  11. +10
    -6
      src/main/java/com/example/application/views/results/MatchView.java
  12. +19
    -38
      src/main/java/com/example/application/views/results/MatchdayView.java
  13. +9
    -14
      src/main/java/com/example/application/views/results/ResultsView.java
  14. +13
    -37
      src/main/java/com/example/application/views/table/TableView.java

+ 1
- 1
db/db_init.sql View File

@ -104,7 +104,7 @@ INSERT INTO "player_info" (url) VALUES ('https://www.chess.com/member/maddinglad
INSERT INTO "player" (name, nickname, info) VALUES ('Maddin', 'maddingladi', (SELECT id from player_info WHERE url='https://www.chess.com/member/maddingladi') );
INSERT INTO "player_info" (url) VALUES ('https://www.chess.com/member/magnus-brother');
INSERT INTO "player" (name, nickname, info) VALUES ('Tariq', 'Magnus-brother', (SELECT id from player_info WHERE url='https://www.chess.com/member/magnus_brother') );
INSERT INTO "player" (name, nickname, info) VALUES ('Tariq', 'Magnus-brother', (SELECT id from player_info WHERE url='https://www.chess.com/member/magnus-brother') );
INSERT INTO "player_info" (url) VALUES ('https://www.chess.com/member/mama-lolo');
INSERT INTO "player" (name, nickname, info) VALUES ('Malte', 'Mama-Lolo', (SELECT id from player_info WHERE url='https://www.chess.com/member/mama-lolo') );


+ 16
- 0
src/main/java/com/example/application/components/navigation/SeasonAndMatchdayNavigation.java View File

@ -0,0 +1,16 @@
package com.example.application.components.navigation;
import com.example.application.navigation.Navigation;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
public class SeasonAndMatchdayNavigation extends HorizontalLayout {
public SeasonAndMatchdayNavigation(Navigation navigation) {
setWidthFull();
setAlignItems(FlexComponent.Alignment.CENTER);
setJustifyContentMode(FlexComponent.JustifyContentMode.END);
add(new Label("Season:"), navigation.getSeasonSelect(), new Label("Matchday:"), navigation.getMatchdaySelect());
}
}

+ 5
- 0
src/main/java/com/example/application/data/entity/Match.java View File

@ -75,4 +75,9 @@ public class Match {
public void setMatchday(Matchday matchday) {
this.matchday = matchday;
}
@Override
public String toString() {
return String.format("%s-vs-%s", player1.getNickname().toLowerCase(), player2.getNickname().toLowerCase());
}
}

+ 15
- 1
src/main/java/com/example/application/data/service/MatchService.java View File

@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
import org.vaadin.artur.helpers.CrudService;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@ -25,9 +26,22 @@ public class MatchService extends CrudService<Match, Integer> {
return repository;
}
public List<CalculatedMatch> getCalculatedMatches(Matchday matchday) {
public List<Match> getMatches(Matchday matchday) {
return repository.findAll().stream()
.filter(match -> match.getMatchday().equals(matchday))
.collect(Collectors.toList());
}
public Optional<Match> getFirstMatch(Matchday matchday) {
List<Match> matches = getMatches(matchday);
if (matches.isEmpty()) {
return Optional.empty();
}
return Optional.of(matches.get(0));
}
public List<CalculatedMatch> getCalculatedMatches(Matchday matchday) {
return getMatches(matchday).stream()
.map(match -> new CalculatedMatch(match, match.getPlayer1(), match.getPlayer2(), getScore1(match), getScore2(match)))
.collect(Collectors.toList());
}


+ 7
- 7
src/main/java/com/example/application/data/service/MatchdayService.java View File

@ -27,15 +27,15 @@ public class MatchdayService extends CrudService<Matchday, Integer> {
}
@NonNull
public List<Matchday> getMatchdaysForSeasonSorted(@NonNull Season season) {
public List<Matchday> getMatchdaysSorted(@NonNull Season season) {
return repository.findAll().stream()
.filter(matchday -> matchday.getSeason().equals(season))
.sorted(Comparator.comparingInt(Matchday::getNumber))
.collect(Collectors.toList());
}
public Optional<Matchday> getFirstMatchdayForSeason(@NonNull Season season) {
List<Matchday> matchdays = getMatchdaysForSeasonSorted(season);
public Optional<Matchday> getFirstMatchday(@NonNull Season season) {
List<Matchday> matchdays = getMatchdaysSorted(season);
if (matchdays.isEmpty()) {
return Optional.empty();
}
@ -43,7 +43,7 @@ public class MatchdayService extends CrudService<Matchday, Integer> {
}
@NonNull
public List<Matchday> getMatchdaysWithActivityForSeasonSorted(@NonNull Season season) {
public List<Matchday> getMatchdaysWithActivitySorted(@NonNull Season season) {
return repository.findAll().stream()
.filter(matchday -> matchday.getSeason().equals(season))
.filter(this::hasActivity)
@ -51,10 +51,10 @@ public class MatchdayService extends CrudService<Matchday, Integer> {
.collect(Collectors.toList());
}
public Optional<Matchday> getLastMatchdayWithActivityForSeason(@NonNull Season season) {
List<Matchday> matchdaysWithActivity = getMatchdaysWithActivityForSeasonSorted(season);
public Optional<Matchday> getLastMatchdayWithActivityOrElseFirstMatchday(@NonNull Season season) {
List<Matchday> matchdaysWithActivity = getMatchdaysWithActivitySorted(season);
if (matchdaysWithActivity.isEmpty()) {
return Optional.empty();
return getFirstMatchday(season);
}
return Optional.of(matchdaysWithActivity.get(matchdaysWithActivity.size()-1));
}


+ 1
- 1
src/main/java/com/example/application/data/service/PlayerService.java View File

@ -42,7 +42,7 @@ public class PlayerService extends CrudService<Player, Integer> {
List<Player> players = repository.findAll();
public PlayerForTableProvider(Matchday matchday) {
matchdays.addAll(matchdayService.getMatchdaysForSeasonSorted(matchday.getSeason()).stream()
matchdays.addAll(matchdayService.getMatchdaysSorted(matchday.getSeason()).stream()
.filter(matchdayToFilter -> matchdayToFilter.getNumber() <= matchday.getNumber())
.collect(Collectors.toList()));


+ 422
- 0
src/main/java/com/example/application/navigation/Navigation.java View File

@ -0,0 +1,422 @@
package com.example.application.navigation;
import com.example.application.data.entity.Match;
import com.example.application.data.entity.Matchday;
import com.example.application.data.entity.Season;
import com.example.application.data.service.MatchService;
import com.example.application.data.service.MatchdayService;
import com.example.application.data.service.SeasonService;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class Navigation implements HasUrlParameter<String> {
// TODO: show dropdown menus also for invalid URLs (with content that fits the situation)
private final String route;
private final boolean onlyMatchdaysWithActivity;
private final List<Runnable> runnablesToBeRunAfterSelection = new ArrayList<>();
private final SeasonService seasonService;
private final MatchdayService matchdayService;
private final MatchService matchService;
private final List<Season> seasonList = new ArrayList<>();
private final List<Matchday> matchdayList = new ArrayList<>();
private final List<Match> matchList = new ArrayList<>();
private final Select<Season> seasonSelect = new Select<>();
private final Select<Matchday> matchdaySelect = new Select<>();
private final Select<Match> matchSelect = new Select<>();
private String seasonParam;
private String matchdayParam;
private String matchParam;
private boolean autoselectSeason = false;
private boolean autoselectMatchday = false;
private boolean autoselectMatch = false;
private final Label invalidUrlLabel = new Label();
private final Button prevMatchdayButton = new Button(new Icon(VaadinIcon.ARROW_LEFT));
private final Button nextMatchdayButton = new Button(new Icon(VaadinIcon.ARROW_RIGHT));
public Navigation(String route,
@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
this(route, seasonService, matchdayService, matchService, false);
}
public Navigation(String route,
@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService,
boolean onlyMatchdaysWithActivity) {
this.route = route;
this.seasonService = seasonService;
this.matchdayService = matchdayService;
this.matchService = matchService;
this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
fillSeasonSelectWithData();
seasonSelect.addValueChangeListener(seasonSelectValueChangeListener());
matchdaySelect.addValueChangeListener(matchdaySelectValueChangeListener());
matchSelect.addValueChangeListener(matchSelectValueChangeListener());
}
public void setAutoselectSeason(boolean autoselectSeason) {
this.autoselectSeason = autoselectSeason;
}
public void setAutoselectMatchday(boolean autoselectMatchday) {
this.autoselectMatchday = autoselectMatchday;
}
public void setAutoselectMatch(boolean autoselectMatch) {
this.autoselectMatch = autoselectMatch;
}
// TODO: run the runnables after each selection (anyhow), then push history state (UI.getCurrent().getPage().getHistory().pushState(null, "http://host.com/person?action=edit&id=1");).
// Navigate as little as possible.
private void updateUrl() {
String params = NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", route, params));
}
private HasValue.ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<Select<Matchday>, Matchday>> matchdaySelectValueChangeListener() {
return matchdayChangeEvent -> {
Matchday matchday = matchdayChangeEvent.getValue();
if (matchday != null) {
matchParam = matchday.toString();
updateUrl();
runnablesToBeRunAfterSelection.forEach(Runnable::run);
}
};
}
private HasValue.ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<Select<Season>, Season>> seasonSelectValueChangeListener() {
return seasonChangeEvent -> {
Season newSeason = seasonChangeEvent.getValue();
if (newSeason != null) {
String seasonParam = newSeason.toString();
String matchdayParam = null;
Matchday matchdayInNewSeason = null;
Matchday matchdayInOldSeason = matchdaySelect.getValue();
if (matchdayInOldSeason != null) {
matchdayParam = matchdayInOldSeason.toString();
matchdayInNewSeason = getMatchdayFromParam(matchdayParam, newSeason);
}
matchdayParam = matchdayInNewSeason == null ? "1" : matchdayParam;
this.seasonParam = seasonParam;
this.matchdayParam = matchdayParam;
this.matchParam = null;
updateUrl();
runnablesToBeRunAfterSelection.forEach(Runnable::run);
}
};
}
private HasValue.ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<Select<Match>, Match>> matchSelectValueChangeListener() {
return matchChangeEvent -> {
Match match = matchChangeEvent.getValue();
if (match != null) {
matchParam = match.toString();
updateUrl();
runnablesToBeRunAfterSelection.forEach(Runnable::run); // TODO: offer different lists for season, matchday, match
}
};
}
private void fillSeasonSelectWithData() {
seasonList.clear();
seasonList.addAll(seasonService.getAllSeasonsSorted());
seasonSelect.setItems(seasonList);
}
private void fillMatchdaySelectWithData(Season season) {
matchdayList.clear();
List<Matchday> matchdaysToAdd = onlyMatchdaysWithActivity ?
matchdayService.getMatchdaysWithActivitySorted(season) : matchdayService.getMatchdaysSorted(season);
matchdayList.addAll(matchdaysToAdd);
matchdaySelect.setItems(matchdayList);
}
private void fillMatchSelectWithData(Matchday matchday) {
matchList.clear();
matchList.addAll(matchService.getMatches(matchday));
matchSelect.setItems(matchList);
}
private boolean isMatchDayParamValid(@NonNull String matchdayParam) {
return matchdayList.stream().anyMatch(matchday -> matchdayParam.equals(matchday.toString()));
}
private void navigate(String seasonParam, String matchdayParam, String matchParam) { // TODO: change this to String... -> see where you need which parameters
UI.getCurrent().navigate(String.format("%s/%s", route, NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam)));
}
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
Map<UrlParameterType, String> map = NavigationUtils.getParameterMap(param);
setParameter(map.get(UrlParameterType.SEASON), map.get(UrlParameterType.MATCHDAY), map.get(UrlParameterType.MATCH));
}
private boolean paramInvalid(@Nullable String param) {
return param == null || param.equals("");
}
private void noMatchFound(Season season, Matchday matchday) {
invalidUrlLabel.setText(String.format("No Match found in Matchday %s in Season %s!", matchday.toString(), season.toString()));
}
private void matchFound(Season season, Matchday matchday, Match match) {
matchSelect.setValue(match);
navigate(season.toString(), matchday.toString(), match.toString());
}
private void noMatchdayFound(Season season) {
invalidUrlLabel.setText(String.format("No Matchday found in Season %s!", season.toString()));
}
private void autoselectMatch(Season season, Matchday matchday) {
Optional<Match> firstMatch = matchService.getFirstMatch(matchday);
firstMatch.ifPresentOrElse(
match -> matchFound(season, matchday, match),
() -> noMatchFound(season, matchday));
}
private void matchdayFound(Season season, Matchday matchday, String matchParam) {
matchdaySelect.setValue(matchday);
fillMatchSelectWithData(matchday);
if (paramInvalid(matchParam) && autoselectMatch) {
autoselectMatch(season, matchday);
return;
}
navigate(season.toString(), matchday.toString(), matchParam);
}
private void noSeasonFound() {
invalidUrlLabel.setText("No Season found!");
}
private void autoselectMatchday(Season season, String matchParam) {
Optional<Matchday> latestMatchday = matchdayService.getLastMatchdayWithActivityOrElseFirstMatchday(season);
latestMatchday.ifPresentOrElse(
matchday -> matchdayFound(season, matchday, matchParam),
() -> noMatchdayFound(season));
}
private void seasonFound(Season season, String matchdayParam, String matchParam) {
seasonSelect.setValue(season);
fillMatchdaySelectWithData(season);
if (paramInvalid(matchdayParam) && autoselectMatchday) {
autoselectMatchday(season, matchParam);
return;
}
navigate(season.toString(), matchdayParam, matchParam);
}
private void autoselectSeason(String matchdayParam, String matchParam) {
Optional<Season> latestSeason = seasonService.getLatestSeason();
latestSeason.ifPresentOrElse(
season -> seasonFound(season, matchdayParam, matchParam),
this::noSeasonFound);
}
private boolean autoselectIfNecessary(String seasonParam, String matchdayParam, String matchParam) {
if (paramInvalid(seasonParam) && autoselectSeason) {
autoselectSeason(matchdayParam, matchParam);
return true;
}
if (paramInvalid(matchdayParam) && autoselectMatchday) {
autoselectMatchday(seasonSelect.getValue(), matchParam);
return true;
}
if (paramInvalid(matchParam) && autoselectMatch) {
autoselectMatch(seasonSelect.getValue(), matchdaySelect.getValue());
return true;
}
return false;
}
public void setParameter(String seasonParam, String matchdayParam, String matchParam) {
if (autoselectIfNecessary(seasonParam, matchdayParam, matchParam)) {
for (Runnable runnable : runnablesToBeRunAfterSelection) {
runnable.run();
}
return;
}
Season season = getSeasonFromParam(seasonParam);
if (season != null) {
seasonSelect.setValue(season);
this.seasonParam = seasonParam;
fillMatchdaySelectWithData(season);
} else if (autoselectSeason) {
invalidUrlLabel.setText(String.format("Invalid URL! Season \"%s\" does not exist in the database!", seasonParam));
return;
}
Matchday matchday = getMatchdayFromParam(matchdayParam);
if (matchday != null) {
matchdaySelect.setValue(matchday);
this.matchdayParam = matchdayParam;
fillMatchSelectWithData(matchday);
configureButtons();
} else if (autoselectMatchday) {
String messageExtra = onlyMatchdaysWithActivity ? " or has no games played yet" : "";
invalidUrlLabel.setText(String.format("Invalid URL! Matchday \"%s\" in Season \"%s\" does not exist in the database%s!", matchdayParam, seasonParam, messageExtra));
return;
}
Match match = getMatchFromParam(matchParam);
if (match != null) {
matchSelect.setValue(match);
this.matchParam = matchParam;
} else if (autoselectMatch) {
invalidUrlLabel.setText(String.format("Invalid URL: Match \"%s\" in Matchday \"%s\" in Season \"%s\" does not exist in the database!", matchParam, matchdayParam, seasonParam));
}
for (Runnable runnable : runnablesToBeRunAfterSelection) {
runnable.run();
}
}
@Nullable
private Season getSeasonFromParam(@Nullable String seasonParam) {
if (seasonParam == null) {
return null;
}
for (Season season : seasonList) {
if (seasonParam.equals(season.toString())) {
return season;
}
}
return null;
}
@Nullable
private Matchday getMatchdayFromParam(@Nullable String matchdayParam) {
return getMatchdayFromParam(matchdayParam, null);
}
@Nullable
private Matchday getMatchdayFromParam(@Nullable String matchdayParam, @Nullable Season season) {
if (matchdayParam == null) {
return null;
}
List<Matchday> matchdayList = season == null ? this.matchdayList : matchdayService.getMatchdaysSorted(season);
for (Matchday matchday : matchdayList) {
if (matchdayParam.equals(matchday.toString())) {
return matchday;
}
}
return null;
}
@Nullable
private Match getMatchFromParam(@Nullable String matchParam) {
if (matchParam == null) {
return null;
}
for (Match match : matchList) {
if (matchParam.equals(match.toString())) {
return match;
}
}
return null;
}
public void addRunnableToBeRunAfterSelection(Runnable runnable) {
runnablesToBeRunAfterSelection.add(runnable);
}
private void configureButtons() {
prevMatchdayButton.setEnabled(isMatchDayParamValid(getPrevMatchdayParam()));
prevMatchdayButton.addClickListener(getButtonClickListener(getPrevMatchdayParam()));
nextMatchdayButton.setEnabled(isMatchDayParamValid(getNextMatchdayParam()));
nextMatchdayButton.addClickListener(getButtonClickListener(getNextMatchdayParam()));
}
private ComponentEventListener<ClickEvent<Button>> getButtonClickListener(String matchdayParam) {
return buttonClickEvent -> navigate(seasonParam, matchdayParam, matchParam);
}
private String getPrevMatchdayParam() {
try {
return String.valueOf(Integer.parseInt(matchdayParam) - 1);
} catch (NumberFormatException e) {
return "";
}
}
private String getNextMatchdayParam() {
try {
return String.valueOf(Integer.parseInt(matchdayParam) + 1);
} catch (NumberFormatException e) {
return "";
}
}
public Optional<Matchday> getSelectedMatchday() {
return matchdaySelect.getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return seasonSelect.getOptionalValue();
}
public Optional<Match> getSelectedMatch() {
return matchSelect.getOptionalValue();
}
public Button getPrevMatchdayButton() {
return prevMatchdayButton;
}
public Button getNextMatchdayButton() {
return nextMatchdayButton;
}
public Label getInvalidUrlLabel() {
return invalidUrlLabel;
}
public Select<Season> getSeasonSelect() {
return seasonSelect;
}
public Select<Matchday> getMatchdaySelect() {
return matchdaySelect;
}
public Select<Match> getMatchSelect() {
return matchSelect;
}
public void selectMatch(Match match) {
navigate(seasonParam, matchdayParam, match.toString());
}
}

+ 39
- 0
src/main/java/com/example/application/navigation/NavigationUtils.java View File

@ -0,0 +1,39 @@
package com.example.application.navigation;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.Map;
public class NavigationUtils {
public static Map<UrlParameterType, String> getParameterMap(@WildcardParameter String param) {
Map<UrlParameterType, String> map = new HashMap<>();
String[] params = param.split("/");
switch (params.length) {
case 3:
map.put(UrlParameterType.MATCH, params[2]);
case 2:
map.put(UrlParameterType.MATCHDAY, params[1]);
case 1:
map.put(UrlParameterType.SEASON, params[0]);
default:
break;
}
return map;
}
@NonNull
public static String getWildcardParam(String... params) {
StringBuilder stringBuilder = new StringBuilder();
for (String param : params) {
if (param == null || param.equals("")) {
break;
}
stringBuilder.append(param).append("/");
}
return stringBuilder.toString();
}
}

+ 7
- 0
src/main/java/com/example/application/navigation/UrlParameterType.java View File

@ -0,0 +1,7 @@
package com.example.application.navigation;
public enum UrlParameterType {
SEASON,
MATCHDAY,
MATCH
}

+ 0
- 258
src/main/java/com/example/application/views/abstractnavigation/SeasonAndMatchdayNavigation.java View File

@ -1,258 +0,0 @@
package com.example.application.views.abstractnavigation;
import com.example.application.data.entity.Matchday;
import com.example.application.data.entity.Season;
import com.example.application.data.service.MatchdayService;
import com.example.application.data.service.SeasonService;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.select.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class SeasonAndMatchdayNavigation {
// TODO: show dropdown menus also for invalid URLs (with content that fits the situation)
private final SeasonService seasonService;
private final MatchdayService matchdayService;
private final Label invalidUrlLabel = new Label();
private final HorizontalLayout selectionLayout = new HorizontalLayout();
private final List<Season> seasonList = new ArrayList<>();
private final Select<Season> seasonSelect = new Select<>();
private final List<Matchday> matchdayList = new ArrayList<>();
private final Select<Matchday> matchdaySelect = new Select<>();
private final String route;
private final boolean onlyMatchdaysWithActivity;
private Runnable runnableToBeRunAfterSelection;
private final Button prevButton = new Button(new Icon(VaadinIcon.ARROW_LEFT));
private final Button nextButton = new Button(new Icon(VaadinIcon.ARROW_RIGHT));
private String seasonParam;
private String matchdayParam;
public SeasonAndMatchdayNavigation(String route,
@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService) {
this(route, seasonService, matchdayService, false);
}
public SeasonAndMatchdayNavigation(String route,
@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
boolean onlyMatchdaysWithActivity) {
this.route = route;
this.seasonService = seasonService;
this.matchdayService = matchdayService;
this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
configureSelectionLayout();
}
private void configureSelectionLayout() {
selectionLayout.setWidthFull();
selectionLayout.setAlignItems(FlexComponent.Alignment.CENTER);
selectionLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
selectionLayout.add(new Label("Season:"), seasonSelect, new Label("Matchday:"), matchdaySelect);
seasonSelect.addValueChangeListener(seasonSelectValueChangeListener());
matchdaySelect.addValueChangeListener(matchdaySelectValueChangeListener());
// provide data
fillSeasonSelectWithData();
}
private HasValue.ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<Select<Matchday>, Matchday>> matchdaySelectValueChangeListener() {
return matchdayChangeEvent -> {
Season season = seasonSelect.getValue();
Matchday matchday = matchdayChangeEvent.getValue();
if (season != null && matchday != null) {
String seasonParam = season.toString();
String matchdayParam = matchday.toString();
navigate(seasonParam, matchdayParam);
}
};
}
private HasValue.ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<Select<Season>, Season>> seasonSelectValueChangeListener() {
return seasonChangeEvent -> {
Season newSeason = seasonChangeEvent.getValue();
if (newSeason != null) {
String seasonParam = newSeason.toString();
String matchdayParam = null;
Matchday matchdayInNewSeason = null;
Matchday matchdayInOldSeason = matchdaySelect.getValue();
if (matchdayInOldSeason != null) {
matchdayParam = matchdayInOldSeason.toString();
matchdayInNewSeason = getMatchdayFromParam(matchdayParam, newSeason);
}
matchdayParam = matchdayInNewSeason == null ? "1" : matchdayParam;
navigate(seasonParam, matchdayParam);
}
};
}
private void fillSeasonSelectWithData() {
seasonList.clear();
seasonList.addAll(seasonService.getAllSeasonsSorted());
seasonSelect.setItems(seasonList);
}
private void fillMatchdaySelectWithData() {
matchdayList.clear();
List<Matchday> matchdaysToAdd = onlyMatchdaysWithActivity ?
matchdayService.getMatchdaysWithActivityForSeasonSorted(seasonSelect.getValue()) : matchdayService.getMatchdaysForSeasonSorted(seasonSelect.getValue());
matchdayList.addAll(matchdaysToAdd);
matchdaySelect.setItems(matchdayList);
}
private boolean isMatchDayParamValid(@NonNull String matchdayParam) {
return matchdayList.stream().anyMatch(matchday -> matchdayParam.equals(matchday.toString()));
}
private void navigate(String seasonParam, String matchdayParam) {
UI.getCurrent().navigate(String.format("%s/%s/%s/", route, seasonParam, matchdayParam));
// setParameter(seasonParam, matchdayParam);
}
public void setParameter(String seasonParam, String matchdayParam) {
// TODO: handle corner case where first matchday has no active games yet: still show first matchday
if (seasonParam == null || seasonParam.equals("") || matchdayParam == null || matchdayParam.equals("")) {
Optional<Season> latestSeason = seasonService.getLatestSeason();
if (latestSeason.isPresent()) {
Optional<Matchday> latestMatchday = matchdayService.getLastMatchdayWithActivityForSeason(latestSeason.get());
if (latestMatchday.isPresent()) {
seasonParam = latestSeason.get().toString();
matchdayParam = latestMatchday.get().toString();
navigate(seasonParam, matchdayParam);
setParameter(seasonParam, matchdayParam);
}
}
return;
}
Season season = getSeasonFromParam(seasonParam);
if (season == null) {
invalidUrlLabel.setText(String.format("Invalid URL! Season \"%s\" does not exist in the database!", seasonParam));
return;
}
seasonSelect.setValue(season);
this.seasonParam = seasonParam;
fillMatchdaySelectWithData();
Matchday matchday = getMatchdayFromParam(matchdayParam);
if (matchday == null) {
String messageExtra = onlyMatchdaysWithActivity ? " or has no games played yet" : "";
invalidUrlLabel.setText(String.format("Invalid URL! Matchday \"%s\" in Season \"%s\" does not exist in the database%s!", matchdayParam, seasonParam, messageExtra));
return;
}
matchdaySelect.setValue(matchday);
this.matchdayParam = matchdayParam;
configureButtons();
if ((runnableToBeRunAfterSelection) != null) {
runnableToBeRunAfterSelection.run();
}
}
@Nullable
private Season getSeasonFromParam(@NonNull String seasonParam) {
for (Season season : seasonList) {
if (seasonParam.equals(season.toString())) {
return season;
}
}
return null;
}
@Nullable
private Matchday getMatchdayFromParam(@NonNull String matchdayParam) {
return getMatchdayFromParam(matchdayParam, null);
}
@Nullable
private Matchday getMatchdayFromParam(@NonNull String matchdayParam, @Nullable Season season) {
List<Matchday> matchdayList = season == null ? this.matchdayList : matchdayService.getMatchdaysForSeasonSorted(season);
for (Matchday matchday : matchdayList) {
if (matchdayParam.equals(matchday.toString())) {
return matchday;
}
}
return null;
}
public void setRunnableToBeRunAfterSelection(Runnable runnableToBeRunAfterSelection) {
this.runnableToBeRunAfterSelection = runnableToBeRunAfterSelection;
}
private void configureButtons() {
prevButton.setEnabled(isMatchDayParamValid(getPrevMatchdayParam()));
prevButton.addClickListener(getButtonClickListener(getPrevMatchdayParam()));
nextButton.setEnabled(isMatchDayParamValid(getNextMatchdayParam()));
nextButton.addClickListener(getButtonClickListener(getNextMatchdayParam()));
}
private ComponentEventListener<ClickEvent<Button>> getButtonClickListener(String matchdayParam) {
return buttonClickEvent -> navigate(seasonParam, matchdayParam);
}
private String getPrevMatchdayParam() {
try {
return String.valueOf(Integer.parseInt(matchdayParam) - 1);
} catch (NumberFormatException e) {
return "";
}
}
private String getNextMatchdayParam() {
try {
return String.valueOf(Integer.parseInt(matchdayParam) + 1);
} catch (NumberFormatException e) {
return "";
}
}
public Optional<Matchday> getSelectedMatchday() {
return matchdaySelect.getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return seasonSelect.getOptionalValue();
}
public HorizontalLayout getSelectionLayout() {
return selectionLayout;
}
public Button getPrevButton() {
return prevButton;
}
public Button getNextButton() {
return nextButton;
}
public Label getInvalidUrlLabel() {
return invalidUrlLabel;
}
}

+ 10
- 6
src/main/java/com/example/application/views/results/MatchView.java View File

@ -1,22 +1,26 @@
package com.example.application.views.results;
import com.example.application.navigation.Navigation;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
public class MatchView extends Div implements HasUrlParameter<String[]> {
public class MatchView extends Div {
private final Navigation navigation;
private final Label label = new Label();
// private final ChessComService chessComService;
// private final PlayerService playerService;
// public ResultsViewRight(@Autowired ChessComService chessComService, @Autowired PlayerService playerService) {
public MatchView() {
public MatchView(Navigation navigation) {
this.navigation = navigation;
navigation.addRunnableToBeRunAfterSelection(()-> label.setText(navigation.getSelectedMatch().toString()));
add(label);
// this.chessComService = chessComService;
// this.playerService = playerService;
}
@Override
public void setParameter(BeforeEvent beforeEvent, String[] SeasonParamAndMatchdayParamAndGameParam) {
}
}

+ 19
- 38
src/main/java/com/example/application/views/results/MatchdayView.java View File

@ -1,13 +1,13 @@
package com.example.application.views.results;
import com.example.application.components.navigation.SeasonAndMatchdayNavigation;
import com.example.application.data.bean.CalculatedMatch;
import com.example.application.data.entity.Match;
import com.example.application.data.entity.Matchday;
import com.example.application.data.service.MatchService;
import com.example.application.data.service.MatchdayService;
import com.example.application.data.service.SeasonService;
import com.example.application.navigation.Navigation;
import com.example.application.utils.StringUtils;
import com.example.application.utils.VaadinUtils;
import com.example.application.views.abstractnavigation.SeasonAndMatchdayNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.grid.Grid;
@ -16,19 +16,18 @@ import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.selection.SelectionEvent;
import com.vaadin.flow.data.selection.SelectionListener;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Optional;
public class MatchdayView extends VerticalLayout implements HasUrlParameter<String> {
public class MatchdayView extends VerticalLayout {
private final MatchService matchService;
private final SeasonAndMatchdayNavigation seasonAndMatchdayNavigation;
private final Navigation navigation;
private final VerticalLayout matchdayLayout = new VerticalLayout();
private final Label matchdayHeader = new Label();
@ -37,13 +36,13 @@ public class MatchdayView extends VerticalLayout implements HasUrlParameter<Stri
private final Button prevButton;
private final Button nextButton;
public MatchdayView(@Autowired SeasonService seasonService, @Autowired MatchdayService matchdayService, @Autowired MatchService matchService) {
this.seasonAndMatchdayNavigation = new SeasonAndMatchdayNavigation("results", seasonService, matchdayService);
this.seasonAndMatchdayNavigation.setRunnableToBeRunAfterSelection(this::configureContent);
public MatchdayView(Navigation navigation, @Autowired MatchService matchService) {
this.navigation = navigation;
this.navigation.addRunnableToBeRunAfterSelection(this::configureContent);
this.matchService = matchService;
prevButton = seasonAndMatchdayNavigation.getPrevButton();
nextButton = seasonAndMatchdayNavigation.getNextButton();
prevButton = navigation.getPrevMatchdayButton();
nextButton = navigation.getNextMatchdayButton();
configureContentLayout();
}
@ -52,12 +51,11 @@ public class MatchdayView extends VerticalLayout implements HasUrlParameter<Stri
// LAYOUT //
////////////
protected void configureContentLayout() {
setWidthFull();
setHeightFull();
setAlignItems(FlexComponent.Alignment.CENTER);
add(seasonAndMatchdayNavigation.getSelectionLayout(), matchdayLayout);
add(new SeasonAndMatchdayNavigation(navigation), matchdayLayout);
// TODO add background color for content
matchdayHeader.addClassName("matchday_header"); // TODO: add dates
@ -97,6 +95,11 @@ public class MatchdayView extends VerticalLayout implements HasUrlParameter<Stri
grid.addThemeVariants(GridVariant.LUMO_NO_BORDER,
GridVariant.LUMO_NO_ROW_BORDERS, GridVariant.LUMO_ROW_STRIPES);
grid.addSelectionListener((SelectionListener<Grid<CalculatedMatch>, CalculatedMatch>) selectionEvent -> {
Optional<CalculatedMatch> calculatedMatch = selectionEvent.getFirstSelectedItem();
calculatedMatch.ifPresent(match -> navigation.selectMatch(match.getMatch()));
});
}
private String getResultString(CalculatedMatch match) {
@ -109,32 +112,10 @@ public class MatchdayView extends VerticalLayout implements HasUrlParameter<Stri
/////////////
protected void configureContent() {
Optional<Matchday> selectedMatchday = seasonAndMatchdayNavigation.getSelectedMatchday();
Optional<Matchday> selectedMatchday = navigation.getSelectedMatchday();
selectedMatchday.ifPresent(matchday -> {
matchdayHeader.setText(String.format("Matchday %s", matchday.toString()));
grid.setItems(matchService.getCalculatedMatches(matchday));
});
}
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
String[] params = param.split("/");
String seasonParam;
String matchdayParam;
switch (params.length) {
case 0:
seasonParam = "";
matchdayParam = "";
break;
case 1:
seasonParam = params[0];
matchdayParam = "";
break;
default:
seasonParam = params[0];
matchdayParam = params[1];
}
seasonAndMatchdayNavigation.setParameter(seasonParam, matchdayParam);
}
}

+ 9
- 14
src/main/java/com/example/application/views/results/ResultsView.java View File

@ -1,6 +1,7 @@
package com.example.application.views.results;
import com.example.application.data.service.*;
import com.example.application.navigation.Navigation;
import com.example.application.views.main.MainView;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.html.Div;
@ -15,6 +16,8 @@ public class ResultsView extends Div implements HasUrlParameter<String> {
private final SplitLayout splitLayout = new SplitLayout();
private final Navigation navigation;
private final MatchdayView matchdayView;
private final MatchView matchView;
@ -24,8 +27,11 @@ public class ResultsView extends Div implements HasUrlParameter<String> {
@Autowired ChessComService chessComService,
@Autowired PlayerService playerService) {
this.matchdayView = new MatchdayView(seasonService, matchdayService, matchService);
this.matchView = new MatchView();
this.navigation = new Navigation("results", seasonService, matchdayService, matchService);
this.navigation.setAutoselectSeason(true);
this.navigation.setAutoselectMatchday(true);
this.matchdayView = new MatchdayView(navigation, matchService);
this.matchView = new MatchView(navigation);
addClassName("results-view");
@ -56,17 +62,6 @@ public class ResultsView extends Div implements HasUrlParameter<String> {
@Override
public void setParameter(BeforeEvent beforeEvent, @WildcardParameter String param) {
// String[] params = param.split("/");
// if (params.length < 2) {
// // TODO: handle this case!
// return;
// }
// String[] seasonParamAndMatchdayParam = Arrays.copyOfRange(params, 0, 2);
matchdayView.setParameter(beforeEvent, param);
// if (params.length < 3) {
// disableSplit();
// }
// matchView.setParameter(beforeEvent, params);
navigation.setParameter(beforeEvent, param);
}
}

+ 13
- 37
src/main/java/com/example/application/views/table/TableView.java View File

@ -1,12 +1,14 @@
package com.example.application.views.table;
import com.example.application.components.navigation.SeasonAndMatchdayNavigation;
import com.example.application.data.bean.PlayerForTable;
import com.example.application.data.service.MatchService;
import com.example.application.data.service.MatchdayService;
import com.example.application.data.service.PlayerService;
import com.example.application.data.service.SeasonService;
import com.example.application.utils.StringUtils;
import com.example.application.utils.VaadinUtils;
import com.example.application.views.abstractnavigation.SeasonAndMatchdayNavigation;
import com.example.application.navigation.Navigation;
import com.example.application.views.main.MainView;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.grid.ColumnTextAlign;
@ -20,7 +22,6 @@ import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arrays;
import java.util.NoSuchElementException;
@CssImport("./views/table/table-view.css")
@ -31,23 +32,22 @@ public class TableView extends VerticalLayout implements HasUrlParameter<String>
private final PlayerService playerService;
private final SeasonAndMatchdayNavigation seasonAndMatchdayNavigation;
private final Navigation navigation;
private final Label invalidUrlLabel;
private final Grid<PlayerForTable> grid = new Grid<>();
public TableView(@Autowired SeasonService seasonService, @Autowired MatchdayService matchdayService, @Autowired PlayerService playerService) {
public TableView(@Autowired SeasonService seasonService, @Autowired MatchdayService matchdayService, @Autowired MatchService matchService, @Autowired PlayerService playerService) {
this.playerService = playerService;
this.seasonAndMatchdayNavigation = new SeasonAndMatchdayNavigation("table", seasonService, matchdayService, true);
this.seasonAndMatchdayNavigation.setRunnableToBeRunAfterSelection(this::configureContent);
this.invalidUrlLabel = seasonAndMatchdayNavigation.getInvalidUrlLabel();
this.navigation = new Navigation("table", seasonService, matchdayService, matchService, true);
this.navigation.setAutoselectSeason(true);
this.navigation.setAutoselectMatchday(true);
this.navigation.addRunnableToBeRunAfterSelection(this::configureContent);
this.invalidUrlLabel = navigation.getInvalidUrlLabel();
addClassName("table-view");
configureLayout();
// seasonAndMatchdayNavigation.addRunnableToBeRunAfterSeasonParamChange(this::configureContent);
// seasonAndMatchdayNavigation.addRunnableToBeRunAfterMatchdayParamChange(this::configureContent);
}
////////////
@ -59,7 +59,7 @@ public class TableView extends VerticalLayout implements HasUrlParameter<String>
setHeightFull();
setAlignItems(FlexComponent.Alignment.CENTER);
add(seasonAndMatchdayNavigation.getSelectionLayout(), new HorizontalLayout(grid));
add(new SeasonAndMatchdayNavigation(navigation), new HorizontalLayout(grid));
configureGrid();
}
@ -151,7 +151,7 @@ public class TableView extends VerticalLayout implements HasUrlParameter<String>
protected void configureContent() {
try {
grid.setItems(playerService.getPlayersForTable(seasonAndMatchdayNavigation.getSelectedMatchday().orElseThrow()));
grid.setItems(playerService.getPlayersForTable(navigation.getSelectedMatchday().orElseThrow()));
} catch (NoSuchElementException e) {
invalidUrlLabel.setText("No season and/or matchday selected! Please select them above.");
}
@ -159,30 +159,6 @@ public class TableView extends VerticalLayout implements HasUrlParameter<String>
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
String[] params = param.split("/");
String seasonParam;
String matchdayParam;
switch (params.length) {
case 0:
seasonParam = "";
matchdayParam = "";
break;
case 1:
seasonParam = params[0];
matchdayParam = "";
break;
default:
seasonParam = params[0];
matchdayParam = params[1];
}
seasonAndMatchdayNavigation.setParameter(seasonParam, matchdayParam);
}
private String[] getSeasonParamAndMatchdayParam(String[] params) {
if (params.length < 2) {
String seasonParam = params.length == 1 ? params[0] : "";
params = new String[]{seasonParam, ""};
}
return Arrays.copyOfRange(params, 0, 2);
navigation.setParameter(event, param);
}
}

Loading…
Cancel
Save