Browse Source

NICE new structure with generic Navigation

master
GAM 4 years ago
parent
commit
a0438e36c2
46 changed files with 683 additions and 927 deletions
  1. +1
    -1
      README.md
  2. +2
    -1
      src/main/java/app/data/entity/Match.java
  3. +2
    -1
      src/main/java/app/data/entity/Matchday.java
  4. +2
    -1
      src/main/java/app/data/entity/Season.java
  5. +7
    -1
      src/main/java/app/data/service/MatchService.java
  6. +16
    -2
      src/main/java/app/data/service/MatchdayService.java
  7. +7
    -1
      src/main/java/app/data/service/SeasonService.java
  8. +4
    -0
      src/main/java/app/navigation/Navigable.java
  9. +5
    -0
      src/main/java/app/navigation/NavigableService.java
  10. +140
    -5
      src/main/java/app/navigation/Navigation.java
  11. +1
    -0
      src/main/java/app/navigation/NavigationService.java
  12. +2
    -11
      src/main/java/app/navigation/NavigationUtils.java
  13. +127
    -0
      src/main/java/app/navigation/match/MatchNavigation.java
  14. +37
    -0
      src/main/java/app/navigation/match/MatchNavigationService.java
  15. +20
    -0
      src/main/java/app/navigation/match/components/MatchNavigationHeader.java
  16. +99
    -0
      src/main/java/app/navigation/matchday/MatchdayNavigation.java
  17. +33
    -0
      src/main/java/app/navigation/matchday/MatchdayNavigationService.java
  18. +19
    -0
      src/main/java/app/navigation/matchday/components/MatchdayNavigationHeader.java
  19. +14
    -0
      src/main/java/app/navigation/matchday/components/button/MatchdayButtonUtils.java
  20. +35
    -0
      src/main/java/app/navigation/matchday/components/button/NextMatchdayButton.java
  21. +34
    -0
      src/main/java/app/navigation/matchday/components/button/PrevMatchdayButton.java
  22. +0
    -172
      src/main/java/app/navigation/player/PlayerNavigation.java
  23. +0
    -7
      src/main/java/app/navigation/player/PlayerNavigationLevel.java
  24. +0
    -24
      src/main/java/app/navigation/player/PlayerNavigationService.java
  25. +0
    -25
      src/main/java/app/navigation/player/PlayerNavigationUtils.java
  26. +0
    -31
      src/main/java/app/navigation/player/components/PlayerNavigationHeader.java
  27. +0
    -37
      src/main/java/app/navigation/player/components/button/NextPlayerButton.java
  28. +0
    -14
      src/main/java/app/navigation/player/components/button/PlayerButtonUtils.java
  29. +0
    -37
      src/main/java/app/navigation/player/components/button/PrevPlayerButton.java
  30. +0
    -280
      src/main/java/app/navigation/regular/RegularNavigation.java
  31. +0
    -8
      src/main/java/app/navigation/regular/RegularNavigationLevel.java
  32. +0
    -29
      src/main/java/app/navigation/regular/RegularNavigationService.java
  33. +0
    -31
      src/main/java/app/navigation/regular/RegularNavigationUtils.java
  34. +0
    -38
      src/main/java/app/navigation/regular/components/RegularNavigationHeader.java
  35. +0
    -14
      src/main/java/app/navigation/regular/components/button/MatchdayButtonUtils.java
  36. +0
    -37
      src/main/java/app/navigation/regular/components/button/NextMatchdayButton.java
  37. +0
    -36
      src/main/java/app/navigation/regular/components/button/PrevMatchdayButton.java
  38. +9
    -1
      src/main/java/app/utils/EntityStringUtils.java
  39. +7
    -11
      src/main/java/app/views/match/MatchView.java
  40. +7
    -7
      src/main/java/app/views/match/components/EditMatchCard.java
  41. +11
    -11
      src/main/java/app/views/match/components/MatchComponent.java
  42. +9
    -8
      src/main/java/app/views/matchday/MatchdayView.java
  43. +12
    -11
      src/main/java/app/views/matchday/components/MatchdayCard.java
  44. +3
    -18
      src/main/java/app/views/navigation/NavigationViewBase.java
  45. +8
    -7
      src/main/java/app/views/table/TableView.java
  46. +10
    -9
      src/main/java/app/views/table/components/TableCard.java

+ 1
- 1
README.md View File

@ -37,7 +37,7 @@ breakpoints in code for debugging purposes, by clicking next to a line number in
## Project structure ## Project structure
- `MainView.java` in `src/main/java` contains the app.regularNavigation setup. It
- `MainView.java` in `src/main/java` contains the app.matchNavigation setup. It
uses [App Layout](https://vaadin.com/components/vaadin-app-layout). uses [App Layout](https://vaadin.com/components/vaadin-app-layout).
- `app.views` package in `src/main/java` contains the server-side Java app.views of your application. - `app.views` package in `src/main/java` contains the server-side Java app.views of your application.
- `app.views` folder in `frontend/` contains the client-side JavaScript app.views of your application. - `app.views` folder in `frontend/` contains the client-side JavaScript app.views of your application.


+ 2
- 1
src/main/java/app/data/entity/Match.java View File

@ -1,5 +1,6 @@
package app.data.entity; package app.data.entity;
import app.navigation.Navigable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -12,7 +13,7 @@ import java.util.Collection;
@Table(name = "match", @Table(name = "match",
schema = "public", schema = "public",
catalog = "chessleague") catalog = "chessleague")
public class Match extends AbstractEntity {
public class Match extends AbstractEntity implements Navigable {
@ManyToOne(cascade = CascadeType.DETACH) @ManyToOne(cascade = CascadeType.DETACH)
@JoinColumn(name = "matchday", @JoinColumn(name = "matchday",


+ 2
- 1
src/main/java/app/data/entity/Matchday.java View File

@ -1,5 +1,6 @@
package app.data.entity; package app.data.entity;
import app.navigation.Navigable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -12,7 +13,7 @@ import java.util.Collection;
@Table(name = "matchday", @Table(name = "matchday",
schema = "public", schema = "public",
catalog = "chessleague") catalog = "chessleague")
public class Matchday extends AbstractEntity {
public class Matchday extends AbstractEntity implements Navigable {
@ManyToOne(cascade = CascadeType.DETACH) @ManyToOne(cascade = CascadeType.DETACH)
@JoinColumn(name = "season", @JoinColumn(name = "season",


+ 2
- 1
src/main/java/app/data/entity/Season.java View File

@ -1,5 +1,6 @@
package app.data.entity; package app.data.entity;
import app.navigation.Navigable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -12,7 +13,7 @@ import java.util.Collection;
@Table(name = "season", @Table(name = "season",
schema = "public", schema = "public",
catalog = "chessleague") catalog = "chessleague")
public class Season extends AbstractEntity {
public class Season extends AbstractEntity implements Navigable {
@Basic @Basic
@Column(name = "year_start", @Column(name = "year_start",


+ 7
- 1
src/main/java/app/data/service/MatchService.java View File

@ -5,6 +5,7 @@ import app.data.entity.Game;
import app.data.entity.Match; import app.data.entity.Match;
import app.data.entity.Matchday; import app.data.entity.Matchday;
import app.data.repository.MatchRepository; import app.data.repository.MatchRepository;
import app.navigation.NavigableService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.vaadin.artur.helpers.CrudService; import org.vaadin.artur.helpers.CrudService;
@ -14,7 +15,7 @@ import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
public class MatchService extends CrudService<Match, Integer> {
public class MatchService extends CrudService<Match, Integer> implements NavigableService<Match> {
private final MatchRepository repository; private final MatchRepository repository;
@ -66,4 +67,9 @@ public class MatchService extends CrudService<Match, Integer> {
} }
return score; return score;
} }
@Override
public Class<Match> getNavigableClass() {
return Match.class;
}
} }

+ 16
- 2
src/main/java/app/data/service/MatchdayService.java View File

@ -1,8 +1,10 @@
package app.data.service; package app.data.service;
import app.data.bean.CalculatedMatch;
import app.data.entity.Matchday; import app.data.entity.Matchday;
import app.data.entity.Season; import app.data.entity.Season;
import app.data.repository.MatchdayRepository; import app.data.repository.MatchdayRepository;
import app.navigation.NavigableService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -14,12 +16,15 @@ import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
public class MatchdayService extends CrudService<Matchday, Integer> {
public class MatchdayService extends CrudService<Matchday, Integer> implements NavigableService<Matchday> {
private final MatchdayRepository repository; private final MatchdayRepository repository;
public MatchdayService(@Autowired MatchdayRepository repository) {
private final MatchService matchService;
public MatchdayService(@Autowired MatchdayRepository repository, MatchService matchService) {
this.repository = repository; this.repository = repository;
this.matchService = matchService;
} }
@Override @Override
@ -60,4 +65,13 @@ public class MatchdayService extends CrudService<Matchday, Integer> {
public boolean hasActivity(@NonNull Matchday matchday) { public boolean hasActivity(@NonNull Matchday matchday) {
return matchday.getMatches().stream().mapToInt(match -> match.getGames().size()).sum() != 0; return matchday.getMatches().stream().mapToInt(match -> match.getGames().size()).sum() != 0;
} }
@Override
public Class<Matchday> getNavigableClass() {
return Matchday.class;
}
public List<CalculatedMatch> getCalculatedMatches(Matchday matchday) {
return matchService.getCalculatedMatches(matchday);
}
} }

+ 7
- 1
src/main/java/app/data/service/SeasonService.java View File

@ -3,6 +3,7 @@ package app.data.service;
import app.data.entity.Player; import app.data.entity.Player;
import app.data.entity.Season; import app.data.entity.Season;
import app.data.repository.SeasonRepository; import app.data.repository.SeasonRepository;
import app.navigation.NavigableService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.vaadin.artur.helpers.CrudService; import org.vaadin.artur.helpers.CrudService;
@ -13,7 +14,7 @@ import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
public class SeasonService extends CrudService<Season, Integer> {
public class SeasonService extends CrudService<Season, Integer> implements NavigableService<Season> {
private final SeasonRepository repository; private final SeasonRepository repository;
@ -54,4 +55,9 @@ public class SeasonService extends CrudService<Season, Integer> {
.anyMatch(match -> match.getPlayer1().equals(player) || match.getPlayer2().equals(player)))) .anyMatch(match -> match.getPlayer1().equals(player) || match.getPlayer2().equals(player))))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override
public Class<Season> getNavigableClass() {
return Season.class;
}
} }

+ 4
- 0
src/main/java/app/navigation/Navigable.java View File

@ -0,0 +1,4 @@
package app.navigation;
public interface Navigable {
}

+ 5
- 0
src/main/java/app/navigation/NavigableService.java View File

@ -0,0 +1,5 @@
package app.navigation;
public interface NavigableService<T extends Navigable> {
Class<T> getNavigableClass();
}

+ 140
- 5
src/main/java/app/navigation/Navigation.java View File

@ -1,20 +1,64 @@
package app.navigation; package app.navigation;
import app.components.label.ValidationLabel; import app.components.label.ValidationLabel;
import app.utils.EntityStringUtils;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import static app.navigation.NavigationUtils.EDIT;
public abstract class Navigation implements HasUrlParameter<String> { public abstract class Navigation implements HasUrlParameter<String> {
protected String route; protected String route;
protected final List<Class<? extends Navigable>> navigableClasses = new ArrayList<>();
protected final Map<Class<? extends Navigable>, NavigableService<? extends Navigable>> serviceMap = new HashMap<>();
protected final Map<Class<? extends Navigable>, List<? extends Navigable>> listMap = new HashMap<>();
protected final Map<Class<? extends Navigable>, Select<? extends Navigable>> selectMap = new HashMap<>();
protected final List<Runnable> runnablesToBeRunAfterSelection = new ArrayList<>(); protected final List<Runnable> runnablesToBeRunAfterSelection = new ArrayList<>();
protected final ValidationLabel validationLabel = new ValidationLabel(); protected final ValidationLabel validationLabel = new ValidationLabel();
protected boolean editFlag = false; protected boolean editFlag = false;
@SafeVarargs
public Navigation(NavigableService<? extends Navigable>... services) {
for (NavigableService<? extends Navigable> service : services) {
initNavigable(service);
}
if (!navigableClasses.isEmpty()) {
fillChildrenSelectWithData(null, navigableClasses.get(0));
}
}
private <T extends Navigable> void initNavigable(NavigableService<T> service) {
Class<T> clazz = service.getNavigableClass();
navigableClasses.add(clazz);
serviceMap.put(clazz, service);
listMap.put(clazz, new ArrayList<>());
Select<T> select = new Select<>();
select.addValueChangeListener(selectValueChangeListener(clazz));
select.setItemLabelGenerator(EntityStringUtils::getObjectString);
selectMap.put(clazz, select);
}
public final void setRoute(String route) { public final void setRoute(String route) {
this.route = route; this.route = route;
} }
@ -23,8 +67,6 @@ public abstract class Navigation implements HasUrlParameter<String> {
return validationLabel; return validationLabel;
} }
public abstract String getWildcardParam();
protected final String getRoute() { protected final String getRoute() {
if (route != null) return route; if (route != null) return route;
throw new IllegalStateException("Route must be set!"); throw new IllegalStateException("Route must be set!");
@ -36,7 +78,22 @@ public abstract class Navigation implements HasUrlParameter<String> {
runnablesToBeRunAfterSelection.forEach(Runnable::run); runnablesToBeRunAfterSelection.forEach(Runnable::run);
} }
protected abstract void updateUrl();
protected abstract <PARENT extends Navigable, CHILD extends Navigable> List<CHILD> getChildren(@Nullable PARENT parent, @NonNull Class<CHILD> childClass);
protected abstract <T extends Navigable> T getDefaultValue(Class<T> clazz);
protected void updateUrl() {
String[] params = new String[navigableClasses.size()];
for (int i = 0; i < navigableClasses.size(); i++) {
Select<? extends Navigable> select = selectMap.get(navigableClasses.get(i));
if (select.getOptionalValue().isPresent()) {
params[i] = EntityStringUtils.getObjectStringForURL(select.getValue());
}
}
String wildcardParam = NavigationUtils.getWildcardParam(editFlag, params);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), wildcardParam));
}
public boolean editFlag() { public boolean editFlag() {
return editFlag; return editFlag;
@ -50,4 +107,82 @@ public abstract class Navigation implements HasUrlParameter<String> {
} }
} }
public void addRunnableToBeRunAfterSelection(Runnable runnable) {
runnablesToBeRunAfterSelection.add(runnable);
}
protected <T extends Navigable> HasValue.ValueChangeListener<AbstractField.ComponentValueChangeEvent<Select<T>, T>> selectValueChangeListener(Class<T> clazz) {
return event -> {
if (!isLastClass(clazz)) {
Class<? extends Navigable> childClass = getChildClass(clazz);
fillChildrenSelectWithData(event.getValue(), childClass);
autoselect(childClass);
return;
}
doPostSelectionStuff();
};
}
private boolean isLastClass(@NonNull Class<? extends Navigable> clazz) {
return navigableClasses.indexOf(clazz) == navigableClasses.size() - 1;
}
@Nullable
private Class<? extends Navigable> getChildClass(@NonNull Class<? extends Navigable> clazz) {
if (!navigableClasses.contains(clazz) || isLastClass(clazz)) return null;
return navigableClasses.get(navigableClasses.indexOf(clazz) + 1);
}
@SuppressWarnings("unchecked")
protected <CHILD extends Navigable, PARENT extends Navigable> void fillChildrenSelectWithData(PARENT parent, Class<CHILD> childClass) {
List<CHILD> children = getChildren(parent, childClass);
listMap.put(childClass, children);
Select<CHILD> childSelect = (Select<CHILD>) selectMap.get(childClass);
childSelect.setItems(children);
}
@SuppressWarnings("unchecked")
protected <T extends Navigable> void autoselect(Class<T> clazz) {
if (listMap.get(clazz).isEmpty()) {
validationLabel.setText(String.format("No %ss in List!", clazz.getSimpleName()));
validationLabel.setValid(false);
return;
}
Select<T> childSelect = (Select<T>) selectMap.get(clazz);
childSelect.setValue(getDefaultValue(clazz));
}
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
String[] params = param.split("/");
editFlag = params[params.length - 1].equals(EDIT);
for (int i = 0; i < Math.min(params.length, navigableClasses.size()); i++) {
navigateClass(navigableClasses.get(i), params[i]);
}
}
@SuppressWarnings("unchecked")
private <T extends Navigable> void navigateClass(Class<T> clazz, String param) {
List<T> list = (List<T>) listMap.get(clazz);
Select<T> select = (Select<T>) selectMap.get(clazz);
Optional<T> navigable = NavigationUtils.getObjectFromParam(list, param);
if (navigable.isPresent())
select.setValue(navigable.get());
else autoselect(clazz);
}
public String getWildcardParam() {
String[] params = new String[navigableClasses.size()];
for (int i = 0; i < navigableClasses.size(); i++) {
params[i] = getParam(navigableClasses.get(i)).orElse(null);
}
return NavigationUtils.getWildcardParam(editFlag, params);
}
@SuppressWarnings("unchecked")
private <T extends Navigable> Optional<String> getParam(Class<T> clazz) {
Select<T> select = (Select<T>) selectMap.get(clazz);
return select.getOptionalValue().map(EntityStringUtils::getObjectStringForURL);
}
} }

+ 1
- 0
src/main/java/app/navigation/NavigationService.java View File

@ -2,4 +2,5 @@ package app.navigation;
public interface NavigationService<T extends Navigation> { public interface NavigationService<T extends Navigation> {
T getNewNavigation(); T getNewNavigation();
AbstractNavigationHeader<T> getNewNavigationHeader(T navigation);
} }

+ 2
- 11
src/main/java/app/navigation/NavigationUtils.java View File

@ -7,18 +7,12 @@ import org.springframework.lang.NonNull;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class NavigationUtils { public class NavigationUtils {
public static final String EDIT = "edit"; public static final String EDIT = "edit";
private NavigationUtils() { private NavigationUtils() {
} }
public static boolean editFlag(@WildcardParameter String param) {
String[] params = param.split("/");
return params[params.length - 1].equals(EDIT);
}
@NonNull @NonNull
public static String getWildcardParam(boolean editFlag, String... params) { public static String getWildcardParam(boolean editFlag, String... params) {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
@ -32,12 +26,9 @@ public class NavigationUtils {
return stringBuilder.toString(); return stringBuilder.toString();
} }
public static <T> Optional<T> getObjectFromParam(List<T> objectList, Optional<String> param) {
if (param.isEmpty()) {
return Optional.empty();
}
public static <T extends Navigable> Optional<T> getObjectFromParam(List<T> objectList, String param) {
return objectList.stream() return objectList.stream()
.filter(object -> EntityStringUtils.getObjectStringForURL(object).equals(param.get()))
.filter(object -> EntityStringUtils.getObjectStringForURL(object).equals(param))
.findFirst(); .findFirst();
} }
} }

+ 127
- 0
src/main/java/app/navigation/match/MatchNavigation.java View File

@ -0,0 +1,127 @@
package app.navigation.match;
import app.data.entity.Match;
import app.data.entity.Matchday;
import app.data.entity.Season;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.Navigable;
import app.navigation.Navigation;
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.List;
import java.util.Optional;
public class MatchNavigation extends Navigation {
private boolean onlyMatchdaysWithActivity;
public MatchNavigation(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
super(seasonService, matchdayService, matchService);
}
public void setOnlyMatchdaysWithActivity(boolean onlyMatchdaysWithActivity) {
this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
}
@Override
@SuppressWarnings("unchecked")
protected <PARENT extends Navigable, CHILD extends Navigable> List<CHILD> getChildren(@Nullable PARENT parent, @NonNull Class<CHILD> childClass) {
if (childClass.equals(Season.class)) {
return (List<CHILD>) getSeasonService().getAllSeasonsSorted();
}
if (childClass.equals(Matchday.class)) {
assert parent != null;
if (onlyMatchdaysWithActivity)
return (List<CHILD>) getMatchdayService().getMatchdaysWithActivitySortedOrElseListWithOnlyFirstMatchday((Season) parent);
return (List<CHILD>) getMatchdayService().getMatchdaysSorted((Season) parent);
}
if (childClass.equals(Match.class)) {
assert parent != null;
return (List<CHILD>) getMatchService().getMatches((Matchday) parent);
}
throw new UnsupportedOperationException(String.format("This method is not supported for childClass %s", childClass.getSimpleName()));
}
@Override
@SuppressWarnings("unchecked")
protected <T extends Navigable> T getDefaultValue(Class<T> clazz) {
if (clazz.equals(Season.class)) {
assert !getSeasonList().isEmpty();
return (T) getSeasonList().get(getSeasonList().size() - 1);
}
if (clazz.equals(Matchday.class)) {
assert !getMatchdayList().isEmpty();
Matchday matchdayToSelect = getMatchdayList().get(0);
for (Matchday matchday : getMatchdayList())
if (getMatchdayService().hasActivity(matchday)) matchdayToSelect = matchday;
return (T) matchdayToSelect;
}
if (clazz.equals(Match.class)) {
assert !getMatchList().isEmpty();
return (T) getMatchList().get(0);
}
throw new UnsupportedOperationException(String.format("This method is not supported for clazz %s", clazz.getSimpleName()));
}
public SeasonService getSeasonService() {
return (SeasonService) serviceMap.get(Season.class);
}
public MatchdayService getMatchdayService() {
return (MatchdayService) serviceMap.get(Matchday.class);
}
public MatchService getMatchService() {
return (MatchService) serviceMap.get(Match.class);
}
@SuppressWarnings("unchecked")
public List<Season> getSeasonList() {
return (List<Season>) listMap.get(Season.class);
}
@SuppressWarnings("unchecked")
public List<Matchday> getMatchdayList() {
return (List<Matchday>) listMap.get(Matchday.class);
}
@SuppressWarnings("unchecked")
public List<Match> getMatchList() {
return (List<Match>) listMap.get(Match.class);
}
@SuppressWarnings("unchecked")
public Select<Season> getSeasonSelect() {
return (Select<Season>) selectMap.get(Season.class);
}
@SuppressWarnings("unchecked")
public Select<Matchday> getMatchdaySelect() {
return (Select<Matchday>) selectMap.get(Matchday.class);
}
@SuppressWarnings("unchecked")
public Select<Match> getMatchSelect() {
return (Select<Match>) selectMap.get(Match.class);
}
public Optional<Matchday> getSelectedMatchday() {
return getMatchdaySelect().getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return getSeasonSelect().getOptionalValue();
}
public Optional<Match> getSelectedMatch() {
return getMatchSelect().getOptionalValue();
}
}

+ 37
- 0
src/main/java/app/navigation/match/MatchNavigationService.java View File

@ -0,0 +1,37 @@
package app.navigation.match;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.AbstractNavigationHeader;
import app.navigation.NavigationService;
import app.navigation.match.components.MatchNavigationHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MatchNavigationService implements NavigationService<MatchNavigation> {
private final SeasonService seasonService;
private final MatchdayService matchdayService;
private final MatchService matchService;
public MatchNavigationService(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
this.seasonService = seasonService;
this.matchdayService = matchdayService;
this.matchService = matchService;
}
@Override
public MatchNavigation getNewNavigation() {
return new MatchNavigation(seasonService, matchdayService, matchService);
}
@Override
public AbstractNavigationHeader<MatchNavigation> getNewNavigationHeader(MatchNavigation navigation) {
return new MatchNavigationHeader(navigation);
}
}

+ 20
- 0
src/main/java/app/navigation/match/components/MatchNavigationHeader.java View File

@ -0,0 +1,20 @@
package app.navigation.match.components;
import app.navigation.AbstractNavigationHeader;
import app.navigation.match.MatchNavigation;
import com.vaadin.flow.component.html.Label;
public class MatchNavigationHeader extends AbstractNavigationHeader<MatchNavigation> {
public MatchNavigationHeader(MatchNavigation navigation) {
super(navigation);
}
@Override
protected void defineChildren() {
removeAll();
add(new Label("Season:"), navigation.getSeasonSelect());
add(new Label("Matchday:"), navigation.getMatchdaySelect());
add(new Label("Match:"), navigation.getMatchSelect());
}
}

+ 99
- 0
src/main/java/app/navigation/matchday/MatchdayNavigation.java View File

@ -0,0 +1,99 @@
package app.navigation.matchday;
import app.data.entity.Match;
import app.data.entity.Matchday;
import app.data.entity.Season;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.Navigable;
import app.navigation.Navigation;
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.List;
import java.util.Optional;
public class MatchdayNavigation extends Navigation {
private boolean onlyMatchdaysWithActivity;
MatchdayNavigation(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService) {
super(seasonService, matchdayService);
}
public void setOnlyMatchdaysWithActivity(boolean onlyMatchdaysWithActivity) {
this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
}
@Override
@SuppressWarnings({"unchecked", "DuplicatedCode"})
protected <PARENT extends Navigable, CHILD extends Navigable> List<CHILD> getChildren(@Nullable PARENT parent, @NonNull Class<CHILD> childClass) {
if (childClass.equals(Season.class)) {
return (List<CHILD>) getSeasonService().getAllSeasonsSorted();
}
if (childClass.equals(Matchday.class)) {
assert parent != null;
if (onlyMatchdaysWithActivity)
return (List<CHILD>) getMatchdayService().getMatchdaysWithActivitySortedOrElseListWithOnlyFirstMatchday((Season) parent);
return (List<CHILD>) getMatchdayService().getMatchdaysSorted((Season) parent);
}
throw new UnsupportedOperationException(String.format("This method is not supported for childClass %s", childClass.getSimpleName()));
}
@Override
@SuppressWarnings({"unchecked", "DuplicatedCode"})
protected <T extends Navigable> T getDefaultValue(Class<T> clazz) {
if (clazz.equals(Season.class)) {
assert !getSeasonList().isEmpty();
return (T) getSeasonList().get(getSeasonList().size() - 1);
}
if (clazz.equals(Matchday.class)) {
assert !getMatchdayList().isEmpty();
Matchday matchdayToSelect = getMatchdayList().get(0);
for (Matchday matchday : getMatchdayList())
if (getMatchdayService().hasActivity(matchday)) matchdayToSelect = matchday;
return (T) matchdayToSelect;
}
throw new UnsupportedOperationException(String.format("This method is not supported for clazz %s", clazz.getSimpleName()));
}
public SeasonService getSeasonService() {
return (SeasonService) serviceMap.get(Season.class);
}
public MatchdayService getMatchdayService() {
return (MatchdayService) serviceMap.get(Matchday.class);
}
@SuppressWarnings("unchecked")
public List<Season> getSeasonList() {
return (List<Season>) listMap.get(Season.class);
}
@SuppressWarnings("unchecked")
public List<Matchday> getMatchdayList() {
return (List<Matchday>) listMap.get(Matchday.class);
}
@SuppressWarnings("unchecked")
public Select<Season> getSeasonSelect() {
return (Select<Season>) selectMap.get(Season.class);
}
@SuppressWarnings("unchecked")
public Select<Matchday> getMatchdaySelect() {
return (Select<Matchday>) selectMap.get(Matchday.class);
}
public Optional<Matchday> getSelectedMatchday() {
return getMatchdaySelect().getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return getSeasonSelect().getOptionalValue();
}
}

+ 33
- 0
src/main/java/app/navigation/matchday/MatchdayNavigationService.java View File

@ -0,0 +1,33 @@
package app.navigation.matchday;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.AbstractNavigationHeader;
import app.navigation.NavigationService;
import app.navigation.matchday.components.MatchdayNavigationHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MatchdayNavigationService implements NavigationService<MatchdayNavigation> {
private final SeasonService seasonService;
private final MatchdayService matchdayService;
public MatchdayNavigationService(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService) {
this.seasonService = seasonService;
this.matchdayService = matchdayService;
}
@Override
public MatchdayNavigation getNewNavigation() {
return new MatchdayNavigation(seasonService, matchdayService);
}
@Override
public AbstractNavigationHeader<MatchdayNavigation> getNewNavigationHeader(MatchdayNavigation navigation) {
return new MatchdayNavigationHeader(navigation);
}
}

+ 19
- 0
src/main/java/app/navigation/matchday/components/MatchdayNavigationHeader.java View File

@ -0,0 +1,19 @@
package app.navigation.matchday.components;
import app.navigation.AbstractNavigationHeader;
import app.navigation.matchday.MatchdayNavigation;
import com.vaadin.flow.component.html.Label;
public class MatchdayNavigationHeader extends AbstractNavigationHeader<MatchdayNavigation> {
public MatchdayNavigationHeader(MatchdayNavigation navigation) {
super(navigation);
}
@Override
protected void defineChildren() {
removeAll();
add(new Label("Season:"), navigation.getSeasonSelect());
add(new Label("Matchday:"), navigation.getMatchdaySelect());
}
}

+ 14
- 0
src/main/java/app/navigation/matchday/components/button/MatchdayButtonUtils.java View File

@ -0,0 +1,14 @@
package app.navigation.matchday.components.button;
import app.navigation.matchday.MatchdayNavigation;
import java.util.concurrent.atomic.AtomicInteger;
class MatchdayButtonUtils {
static int getMatchdayIndex(MatchdayNavigation matchdayNavigation) {
AtomicInteger index = new AtomicInteger(-1);
matchdayNavigation.getSelectedMatchday().ifPresent(matchday -> index.set(matchdayNavigation.getMatchdayList().indexOf(matchday)));
return index.get();
}
}

+ 35
- 0
src/main/java/app/navigation/matchday/components/button/NextMatchdayButton.java View File

@ -0,0 +1,35 @@
package app.navigation.matchday.components.button;
import app.data.entity.Matchday;
import app.navigation.match.MatchNavigation;
import app.navigation.matchday.MatchdayNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.Optional;
public class NextMatchdayButton extends Button {
private final MatchdayNavigation matchdayNavigation;
public NextMatchdayButton(MatchdayNavigation matchdayNavigation) {
this.matchdayNavigation = matchdayNavigation;
setIcon(VaadinIcon.ARROW_RIGHT.create());
matchdayNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Matchday> nextMatchday = getNextMatchday();
setEnabled(nextMatchday.isPresent());
addClickListener(event -> nextMatchday.ifPresent(matchday -> matchdayNavigation.getMatchdaySelect().setValue(matchday)));
}
private Optional<Matchday> getNextMatchday() {
int index = MatchdayButtonUtils.getMatchdayIndex(matchdayNavigation);
if (index >= 0 && index < matchdayNavigation.getMatchdayList().size() - 1)
return Optional.ofNullable(matchdayNavigation.getMatchdayList().get(index + 1));
return Optional.empty();
}
}

+ 34
- 0
src/main/java/app/navigation/matchday/components/button/PrevMatchdayButton.java View File

@ -0,0 +1,34 @@
package app.navigation.matchday.components.button;
import app.data.entity.Matchday;
import app.navigation.match.MatchNavigation;
import app.navigation.matchday.MatchdayNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.Optional;
public class PrevMatchdayButton extends Button {
private final MatchdayNavigation matchdayNavigation;
public PrevMatchdayButton(MatchdayNavigation matchdayNavigation) {
this.matchdayNavigation = matchdayNavigation;
setIcon(VaadinIcon.ARROW_LEFT.create());
matchdayNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Matchday> prevMatchday = getPrevMatchday();
setEnabled(prevMatchday.isPresent());
addClickListener(event -> prevMatchday.ifPresent(matchday -> matchdayNavigation.getMatchdaySelect().setValue(matchday)));
}
private Optional<Matchday> getPrevMatchday() {
int index = MatchdayButtonUtils.getMatchdayIndex(matchdayNavigation);
if (index > 0) return Optional.ofNullable(matchdayNavigation.getMatchdayList().get(index - 1));
return Optional.empty();
}
}

+ 0
- 172
src/main/java/app/navigation/player/PlayerNavigation.java View File

@ -1,172 +0,0 @@
package app.navigation.player;
import app.components.label.ValidationLabel;
import app.data.entity.Player;
import app.data.entity.Season;
import app.data.service.PlayerService;
import app.data.service.SeasonService;
import app.navigation.Navigation;
import app.navigation.NavigationUtils;
import app.utils.EntityStringUtils;
import com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent;
import com.vaadin.flow.component.HasValue.ValueChangeListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class PlayerNavigation extends Navigation {
private final PlayerService playerService;
private final SeasonService seasonService;
private final List<Player> playerList = new ArrayList<>();
private final List<Season> seasonList = new ArrayList<>();
private final Select<Player> playerSelect = new Select<>();
private final Select<Season> seasonSelect = new Select<>();
public PlayerNavigation(@Autowired PlayerService playerService,
@Autowired SeasonService seasonService) {
this.playerService = playerService;
this.seasonService = seasonService;
fillPlayerSelectWithData();
playerSelect.addValueChangeListener(playerSelectValueChangeListener());
seasonSelect.addValueChangeListener(seasonSelectValueChangeListener());
playerSelect.setItemLabelGenerator(EntityStringUtils::getPlayerString);
seasonSelect.setItemLabelGenerator(EntityStringUtils::getSeasonString);
}
public void addRunnableToBeRunAfterSelection(Runnable runnable) {
runnablesToBeRunAfterSelection.add(runnable);
}
protected void updateUrl() {
String playerParam = null;
String seasonParam = null;
if (playerSelect.getOptionalValue().isPresent())
playerParam = EntityStringUtils.getPlayerStringForURL(playerSelect.getValue());
if (seasonSelect.getOptionalValue().isPresent())
seasonParam = EntityStringUtils.getSeasonStringForURL(seasonSelect.getValue());
String params = NavigationUtils.getWildcardParam(false, playerParam, seasonParam);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params));
}
private ValueChangeListener<ComponentValueChangeEvent<Select<Player>, Player>> playerSelectValueChangeListener() {
return event -> {
fillSeasonSelectWithData(event.getValue());
autoselectSeason();
};
}
private ValueChangeListener<ComponentValueChangeEvent<Select<Season>, Season>> seasonSelectValueChangeListener() {
return event -> doPostSelectionStuff();
}
private void autoselectPlayer() {
if (playerList.isEmpty()) {
validationLabel.setText("No Players in List!");
validationLabel.setValid(false);
return;
}
playerSelect.setValue(playerList.get(0));
}
private void autoselectSeason() {
if (seasonList.isEmpty()) {
validationLabel.setText("No Season in List!");
validationLabel.setValid(false);
return;
}
seasonSelect.setValue(seasonList.get(seasonList.size() - 1));
}
private void fillPlayerSelectWithData() {
playerList.clear();
playerList.addAll(playerService.getAllPlayersSorted());
playerSelect.setItems(playerList);
}
private void fillSeasonSelectWithData(Player player) {
seasonList.clear();
seasonList.addAll(seasonService.getAllSeasonsForPlayerSorted(player));
seasonSelect.setItems(seasonList);
}
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
Map<PlayerNavigationLevel, Optional<String>> map = PlayerNavigationUtils.getParameterMap(param);
navigate(map.get(PlayerNavigationLevel.PLAYER), map.get(PlayerNavigationLevel.SEASON));
}
private void navigate(Optional<String> playerParam, Optional<String> seasonParam) {
Optional<Player> player = NavigationUtils.getObjectFromParam(playerList, playerParam);
if (player.isPresent()) playerSelect.setValue(player.get());
else autoselectPlayer();
Optional<Season> season = NavigationUtils.getObjectFromParam(seasonList, seasonParam);
if (season.isPresent()) seasonSelect.setValue(season.get());
else autoselectSeason();
}
public List<Player> getPlayerList() {
return playerList;
}
public List<Season> getSeasonList() {
return seasonList;
}
public Select<Player> getPlayerSelect() {
return playerSelect;
}
public Select<Season> getSeasonSelect() {
return seasonSelect;
}
public Optional<Player> getSelectedPlayer() {
return playerSelect.getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return seasonSelect.getOptionalValue();
}
public PlayerService getPlayerService() {
return playerService;
}
public SeasonService getSeasonService() {
return seasonService;
}
@Override
public String getWildcardParam() {
return NavigationUtils.getWildcardParam(
false,
getPlayerParam().orElse(null),
getSeasonParam().orElse(null));
}
public Optional<String> getPlayerParam() {
return getSelectedPlayer().map(EntityStringUtils::getPlayerStringForURL);
}
public Optional<String> getSeasonParam() {
return getSelectedSeason().map(EntityStringUtils::getSeasonStringForURL);
}
}

+ 0
- 7
src/main/java/app/navigation/player/PlayerNavigationLevel.java View File

@ -1,7 +0,0 @@
package app.navigation.player;
public enum PlayerNavigationLevel {
NONE,
PLAYER,
SEASON,
}

+ 0
- 24
src/main/java/app/navigation/player/PlayerNavigationService.java View File

@ -1,24 +0,0 @@
package app.navigation.player;
import app.data.service.PlayerService;
import app.data.service.SeasonService;
import app.navigation.NavigationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PlayerNavigationService implements NavigationService<PlayerNavigation> {
private final SeasonService seasonService;
private final PlayerService playerService;
public PlayerNavigationService(@Autowired PlayerService playerService,
@Autowired SeasonService seasonService) {
this.playerService = playerService;
this.seasonService = seasonService;
}
public PlayerNavigation getNewNavigation() {
return new PlayerNavigation(playerService, seasonService);
}
}

+ 0
- 25
src/main/java/app/navigation/player/PlayerNavigationUtils.java View File

@ -1,25 +0,0 @@
package app.navigation.player;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
class PlayerNavigationUtils {
private PlayerNavigationUtils() {
}
@NonNull
static Map<PlayerNavigationLevel, Optional<String>> getParameterMap(@WildcardParameter String param) {
Map<PlayerNavigationLevel, Optional<String>> map = new HashMap<>();
String[] params = param.split("/");
if (params.length >= 1) map.put(PlayerNavigationLevel.PLAYER, Optional.of(params[0]));
if (params.length >= 2) map.put(PlayerNavigationLevel.SEASON, Optional.of(params[1]));
map.putIfAbsent(PlayerNavigationLevel.PLAYER, Optional.empty());
map.putIfAbsent(PlayerNavigationLevel.SEASON, Optional.empty());
return map;
}
}

+ 0
- 31
src/main/java/app/navigation/player/components/PlayerNavigationHeader.java View File

@ -1,31 +0,0 @@
package app.navigation.player.components;
import app.navigation.player.PlayerNavigation;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
public class PlayerNavigationHeader extends HorizontalLayout {
private final PlayerNavigation playerNavigation;
private final Label seasonLabel = new Label("Season:");
private final Label playerLabel = new Label("Player:");
public PlayerNavigationHeader(PlayerNavigation playerNavigation) {
this.playerNavigation = playerNavigation;
defineLayout();
configureChildren();
}
private void defineLayout() {
setWidthFull();
setAlignItems(Alignment.CENTER);
setJustifyContentMode(JustifyContentMode.END);
}
private void configureChildren() {
removeAll();
add(playerLabel, playerNavigation.getPlayerSelect());
add(seasonLabel, playerNavigation.getSeasonSelect());
}
}

+ 0
- 37
src/main/java/app/navigation/player/components/button/NextPlayerButton.java View File

@ -1,37 +0,0 @@
package app.navigation.player.components.button;
import app.data.entity.Player;
import app.navigation.player.PlayerNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.List;
import java.util.Optional;
public class NextPlayerButton extends Button {
private final PlayerNavigation playerNavigation;
public NextPlayerButton(PlayerNavigation playerNavigation) {
this.playerNavigation = playerNavigation;
setIcon(VaadinIcon.ARROW_RIGHT.create());
playerNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Player> nextPlayer = getNextPlayer();
setEnabled(nextPlayer.isPresent());
addClickListener(event -> nextPlayer.ifPresent(player -> playerNavigation.getPlayerSelect().setValue(player)));
}
private Optional<Player> getNextPlayer() {
int index = PlayerButtonUtils.getPlayerIndex(playerNavigation);
if (index < 0) return Optional.empty();
List<Player> playerList = playerNavigation.getPlayerList();
return Optional.ofNullable(playerList.get((index + 1) % playerList.size()));
}
}

+ 0
- 14
src/main/java/app/navigation/player/components/button/PlayerButtonUtils.java View File

@ -1,14 +0,0 @@
package app.navigation.player.components.button;
import app.navigation.player.PlayerNavigation;
import java.util.concurrent.atomic.AtomicInteger;
class PlayerButtonUtils {
static int getPlayerIndex(PlayerNavigation playerNavigation) {
AtomicInteger index = new AtomicInteger(-1);
playerNavigation.getSelectedPlayer().ifPresent(player -> index.set(playerNavigation.getPlayerList().indexOf(player)));
return index.get();
}
}

+ 0
- 37
src/main/java/app/navigation/player/components/button/PrevPlayerButton.java View File

@ -1,37 +0,0 @@
package app.navigation.player.components.button;
import app.data.entity.Player;
import app.navigation.player.PlayerNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.List;
import java.util.Optional;
public class PrevPlayerButton extends Button {
private final PlayerNavigation playerNavigation;
public PrevPlayerButton(PlayerNavigation playerNavigation) {
this.playerNavigation = playerNavigation;
setIcon(VaadinIcon.ARROW_LEFT.create());
playerNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Player> prevPlayer = getPrevPlayer();
setEnabled(prevPlayer.isPresent());
addClickListener(event -> prevPlayer.ifPresent(player -> playerNavigation.getPlayerSelect().setValue(player)));
}
private Optional<Player> getPrevPlayer() {
int index = PlayerButtonUtils.getPlayerIndex(playerNavigation);
if (index < 0) return Optional.empty();
List<Player> playerList = playerNavigation.getPlayerList();
return Optional.ofNullable(playerList.get((index - 1) % playerList.size()));
}
}

+ 0
- 280
src/main/java/app/navigation/regular/RegularNavigation.java View File

@ -1,280 +0,0 @@
package app.navigation.regular;
import app.data.entity.Match;
import app.data.entity.Matchday;
import app.data.entity.Season;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.Navigation;
import app.navigation.NavigationUtils;
import app.utils.EntityStringUtils;
import com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent;
import com.vaadin.flow.component.HasValue.ValueChangeListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class RegularNavigation extends Navigation {
private boolean onlyMatchdaysWithActivity;
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 RegularNavigationLevel regularNavigationLevel = RegularNavigationLevel.SEASON;
public RegularNavigation(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
this.seasonService = seasonService;
this.matchdayService = matchdayService;
this.matchService = matchService;
fillSeasonSelectWithData();
seasonSelect.addValueChangeListener(seasonSelectValueChangeListener());
matchdaySelect.addValueChangeListener(matchdaySelectValueChangeListener());
matchSelect.addValueChangeListener(matchSelectValueChangeListener());
seasonSelect.setItemLabelGenerator(EntityStringUtils::getSeasonString);
matchdaySelect.setItemLabelGenerator(EntityStringUtils::getMatchdayString);
matchSelect.setItemLabelGenerator(EntityStringUtils::getMatchString);
}
public void setOnlyMatchdaysWithActivity(boolean onlyMatchdaysWithActivity) {
this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
}
public void setNavigationLevel(@NonNull RegularNavigationLevel regularNavigationLevel) {
this.regularNavigationLevel = regularNavigationLevel;
}
public void addRunnableToBeRunAfterSelection(Runnable runnable) {
runnablesToBeRunAfterSelection.add(runnable);
}
public boolean seasonEnabled() {
return this.regularNavigationLevel.compareTo(RegularNavigationLevel.SEASON) >= 0;
}
public boolean matchdayEnabled() {
return this.regularNavigationLevel.compareTo(RegularNavigationLevel.MATCHDAY) >= 0;
}
public boolean matchEnabled() {
return this.regularNavigationLevel.compareTo(RegularNavigationLevel.MATCH) >= 0;
}
protected void updateUrl() {
String seasonParam = null;
String matchdayParam = null;
String matchParam = null;
if (seasonEnabled() && seasonSelect.getOptionalValue().isPresent())
seasonParam = EntityStringUtils.getSeasonStringForURL(seasonSelect.getValue());
if (matchdayEnabled() && matchdaySelect.getOptionalValue().isPresent())
matchdayParam = EntityStringUtils.getMatchdayStringForURL(matchdaySelect.getValue());
if (matchEnabled() && matchSelect.getOptionalValue().isPresent())
matchParam = EntityStringUtils.getMatchStringForURL(matchSelect.getValue());
String params = NavigationUtils.getWildcardParam(editFlag, seasonParam, matchdayParam, matchParam);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params));
}
private ValueChangeListener<ComponentValueChangeEvent<Select<Season>, Season>> seasonSelectValueChangeListener() {
return event -> {
if (!seasonEnabled()) throw new IllegalStateException("Cannot select season when it is not enabled!");
if (matchdayEnabled()) {
fillMatchdaySelectWithData(event.getValue());
autoselectMatchday();
return;
}
doPostSelectionStuff();
};
}
private ValueChangeListener<ComponentValueChangeEvent<Select<Matchday>, Matchday>> matchdaySelectValueChangeListener() {
return event -> {
if (!matchdayEnabled()) throw new IllegalStateException("Cannot select matchday when it is not enabled!");
if (matchEnabled()) {
fillMatchSelectWithData(event.getValue());
autoselectMatch();
return;
}
doPostSelectionStuff();
};
}
private ValueChangeListener<ComponentValueChangeEvent<Select<Match>, Match>> matchSelectValueChangeListener() {
return event -> {
if (!matchEnabled()) throw new IllegalStateException("Cannot select match when it is not enabled!");
doPostSelectionStuff();
};
}
private void autoselectSeason() {
if (!seasonEnabled())
throw new IllegalStateException("This method should not be called when season is not enabled!");
if (seasonList.isEmpty()) {
validationLabel.setText("No Seasons in List!");
validationLabel.setValid(false);
return;
}
seasonSelect.setValue(seasonList.get(seasonList.size() - 1));
}
private void autoselectMatchday() {
if (!matchdayEnabled())
throw new IllegalStateException("This method should not be called when matchday is not enabled!");
if (matchdayList.isEmpty()) {
validationLabel.setText("No Matchdays in List!");
validationLabel.setValid(false);
return;
}
Matchday matchdayToSelect = matchdayList.get(0);
for (Matchday matchday : matchdayList) if (matchdayService.hasActivity(matchday)) matchdayToSelect = matchday;
matchdaySelect.setValue(matchdayToSelect);
}
private void autoselectMatch() {
if (!matchEnabled())
throw new IllegalStateException("This method should not be called when match is not enabled!");
if (matchList.isEmpty()) {
validationLabel.setText("No Matches in List!");
validationLabel.setValid(false);
return;
}
matchSelect.setValue(matchList.get(0));
}
private void fillSeasonSelectWithData() {
seasonList.clear();
seasonList.addAll(seasonService.getAllSeasonsSorted());
seasonSelect.setItems(seasonList);
}
private void fillMatchdaySelectWithData(Season season) {
matchdayList.clear();
List<Matchday> matchdaysToAdd = onlyMatchdaysWithActivity ?
matchdayService.getMatchdaysWithActivitySortedOrElseListWithOnlyFirstMatchday(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);
}
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
Map<RegularNavigationLevel, Optional<String>> map = RegularNavigationUtils.getParameterMap(param);
editFlag = NavigationUtils.editFlag(param);
navigate(map.get(RegularNavigationLevel.SEASON), map.get(RegularNavigationLevel.MATCHDAY), map.get(RegularNavigationLevel.MATCH));
}
private void navigate(Optional<String> seasonParam, Optional<String> matchdayParam, Optional<String> matchParam) {
if (!seasonEnabled()) return;
Optional<Season> season = NavigationUtils.getObjectFromParam(seasonList, seasonParam);
if (season.isPresent()) seasonSelect.setValue(season.get());
else autoselectSeason();
if (!matchdayEnabled()) return;
Optional<Matchday> matchday = NavigationUtils.getObjectFromParam(matchdayList, matchdayParam);
if (matchday.isPresent()) matchdaySelect.setValue(matchday.get());
else autoselectMatchday();
if (!matchEnabled()) return;
Optional<Match> match = NavigationUtils.getObjectFromParam(matchList, matchParam);
if (match.isPresent()) matchSelect.setValue(match.get());
else autoselectMatch();
}
public List<Season> getSeasonList() {
return seasonList;
}
public List<Matchday> getMatchdayList() {
return matchdayList;
}
public List<Match> getMatchList() {
return matchList;
}
public Select<Season> getSeasonSelect() {
return seasonSelect;
}
public Select<Matchday> getMatchdaySelect() {
return matchdaySelect;
}
public Select<Match> getMatchSelect() {
return matchSelect;
}
public Optional<Matchday> getSelectedMatchday() {
return matchdaySelect.getOptionalValue();
}
public Optional<Season> getSelectedSeason() {
return seasonSelect.getOptionalValue();
}
public Optional<Match> getSelectedMatch() {
return matchSelect.getOptionalValue();
}
public SeasonService getSeasonService() {
return seasonService;
}
public MatchdayService getMatchdayService() {
return matchdayService;
}
public MatchService getMatchService() {
return matchService;
}
@Override
public String getWildcardParam() {
return NavigationUtils.getWildcardParam(
editFlag,
getSeasonParam().orElse(null),
getMatchdayParam().orElse(null),
getMatchParam().orElse(null));
}
public Optional<String> getSeasonParam() {
return getSelectedSeason().map(EntityStringUtils::getSeasonStringForURL);
}
public Optional<String> getMatchdayParam() {
return getSelectedMatchday().map(EntityStringUtils::getMatchdayStringForURL);
}
public Optional<String> getMatchParam() {
return getSelectedMatch().map(EntityStringUtils::getMatchStringForURL);
}
}

+ 0
- 8
src/main/java/app/navigation/regular/RegularNavigationLevel.java View File

@ -1,8 +0,0 @@
package app.navigation.regular;
public enum RegularNavigationLevel {
NONE,
SEASON,
MATCHDAY,
MATCH
}

+ 0
- 29
src/main/java/app/navigation/regular/RegularNavigationService.java View File

@ -1,29 +0,0 @@
package app.navigation.regular;
import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.navigation.NavigationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RegularNavigationService implements NavigationService<RegularNavigation> {
private final SeasonService seasonService;
private final MatchdayService matchdayService;
private final MatchService matchService;
public RegularNavigationService(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
this.seasonService = seasonService;
this.matchdayService = matchdayService;
this.matchService = matchService;
}
@Override
public RegularNavigation getNewNavigation() {
return new RegularNavigation(seasonService, matchdayService, matchService);
}
}

+ 0
- 31
src/main/java/app/navigation/regular/RegularNavigationUtils.java View File

@ -1,31 +0,0 @@
package app.navigation.regular;
import app.navigation.NavigationUtils;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
class RegularNavigationUtils {
private RegularNavigationUtils() {
}
@NonNull
static Map<RegularNavigationLevel, Optional<String>> getParameterMap(@WildcardParameter String param) {
Map<RegularNavigationLevel, Optional<String>> map = new HashMap<>();
String[] params = param.split("/");
if (params.length >= 1 && !params[0].equals(NavigationUtils.EDIT))
map.put(RegularNavigationLevel.SEASON, Optional.of(params[0]));
if (params.length >= 2 && !params[1].equals(NavigationUtils.EDIT))
map.put(RegularNavigationLevel.MATCHDAY, Optional.of(params[1]));
if (params.length >= 3 && !params[2].equals(NavigationUtils.EDIT))
map.put(RegularNavigationLevel.MATCH, Optional.of(params[2]));
map.putIfAbsent(RegularNavigationLevel.MATCH, Optional.empty());
map.putIfAbsent(RegularNavigationLevel.MATCHDAY, Optional.empty());
map.putIfAbsent(RegularNavigationLevel.SEASON, Optional.empty());
return map;
}
}

+ 0
- 38
src/main/java/app/navigation/regular/components/RegularNavigationHeader.java View File

@ -1,38 +0,0 @@
package app.navigation.regular.components;
import app.navigation.AbstractNavigationHeader;
import app.navigation.Navigation;
import app.navigation.regular.RegularNavigation;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
public class RegularNavigationHeader extends AbstractNavigationHeader<RegularNavigation> {
private final Label seasonLabel = new Label("Season:");
private final Label matchdayLabel = new Label("Matchday:");
private final Label matchLabel = new Label("Match:");
public RegularNavigationHeader(Navigation navigation) {
super(navigation);
}
private void defineLayout() {
setWidthFull();
setAlignItems(FlexComponent.Alignment.CENTER);
setJustifyContentMode(FlexComponent.JustifyContentMode.END);
}
@Override
protected void defineChildren() {
removeAll();
if (navigation.seasonEnabled()) {
add(seasonLabel, navigation.getSeasonSelect());
}
if (navigation.matchdayEnabled()) {
add(matchdayLabel, navigation.getMatchdaySelect());
}
if (navigation.matchEnabled()) {
add(matchLabel, navigation.getMatchSelect());
}
}
}

+ 0
- 14
src/main/java/app/navigation/regular/components/button/MatchdayButtonUtils.java View File

@ -1,14 +0,0 @@
package app.navigation.regular.components.button;
import app.navigation.regular.RegularNavigation;
import java.util.concurrent.atomic.AtomicInteger;
class MatchdayButtonUtils {
static int getMatchdayIndex(RegularNavigation regularNavigation) {
AtomicInteger index = new AtomicInteger(-1);
regularNavigation.getSelectedMatchday().ifPresent(matchday -> index.set(regularNavigation.getMatchdayList().indexOf(matchday)));
return index.get();
}
}

+ 0
- 37
src/main/java/app/navigation/regular/components/button/NextMatchdayButton.java View File

@ -1,37 +0,0 @@
package app.navigation.regular.components.button;
import app.data.entity.Matchday;
import app.navigation.regular.RegularNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.Optional;
public class NextMatchdayButton extends Button {
private final RegularNavigation regularNavigation;
public NextMatchdayButton(RegularNavigation regularNavigation) {
this.regularNavigation = regularNavigation;
if (!regularNavigation.matchdayEnabled())
throw new IllegalStateException("Cannot instantiate NextMatchdayButton when Matchdays are not enabled!");
setIcon(VaadinIcon.ARROW_RIGHT.create());
regularNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Matchday> nextMatchday = getNextMatchday();
setEnabled(nextMatchday.isPresent());
addClickListener(event -> nextMatchday.ifPresent(matchday -> regularNavigation.getMatchdaySelect().setValue(matchday)));
}
private Optional<Matchday> getNextMatchday() {
int index = MatchdayButtonUtils.getMatchdayIndex(regularNavigation);
if (index >= 0 && index < regularNavigation.getMatchdayList().size() - 1)
return Optional.ofNullable(regularNavigation.getMatchdayList().get(index + 1));
return Optional.empty();
}
}

+ 0
- 36
src/main/java/app/navigation/regular/components/button/PrevMatchdayButton.java View File

@ -1,36 +0,0 @@
package app.navigation.regular.components.button;
import app.data.entity.Matchday;
import app.navigation.regular.RegularNavigation;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import java.util.Optional;
public class PrevMatchdayButton extends Button {
private final RegularNavigation regularNavigation;
public PrevMatchdayButton(RegularNavigation regularNavigation) {
this.regularNavigation = regularNavigation;
if (!regularNavigation.matchdayEnabled())
throw new IllegalStateException("Cannot instantiate PrevMatchdayButton when Matchdays are not enabled!");
setIcon(VaadinIcon.ARROW_LEFT.create());
regularNavigation.addRunnableToBeRunAfterSelection(this::configure);
}
private void configure() {
Optional<Matchday> prevMatchday = getPrevMatchday();
setEnabled(prevMatchday.isPresent());
addClickListener(event -> prevMatchday.ifPresent(matchday -> regularNavigation.getMatchdaySelect().setValue(matchday)));
}
private Optional<Matchday> getPrevMatchday() {
int index = MatchdayButtonUtils.getMatchdayIndex(regularNavigation);
if (index > 0) return Optional.ofNullable(regularNavigation.getMatchdayList().get(index - 1));
return Optional.empty();
}
}

+ 9
- 1
src/main/java/app/utils/EntityStringUtils.java View File

@ -26,12 +26,20 @@ public class EntityStringUtils {
return string; return string;
} }
public static String getObjectString(Object object) {
if (object instanceof Player) return getPlayerString((Player) object);
if (object instanceof Season) return getSeasonString((Season) object);
if (object instanceof Matchday) return getMatchdayString((Matchday) object);
if (object instanceof Match) return getMatchString((Match) object);
throw new UnsupportedOperationException(String.format("Cannot get Object String for Type %s!", object.getClass().getSimpleName()));
}
public static String getObjectStringForURL(Object object) { public static String getObjectStringForURL(Object object) {
if (object instanceof Player) return getPlayerStringForURL((Player) object); if (object instanceof Player) return getPlayerStringForURL((Player) object);
if (object instanceof Season) return getSeasonStringForURL((Season) object); if (object instanceof Season) return getSeasonStringForURL((Season) object);
if (object instanceof Matchday) return getMatchdayStringForURL((Matchday) object); if (object instanceof Matchday) return getMatchdayStringForURL((Matchday) object);
if (object instanceof Match) return getMatchStringForURL((Match) object); if (object instanceof Match) return getMatchStringForURL((Match) object);
throw new IllegalStateException(String.format("Cannot get Object String for URL for Type %s!", object.getClass().getSimpleName()));
throw new UnsupportedOperationException(String.format("Cannot get Object String for URL for Type %s!", object.getClass().getSimpleName()));
} }
public static String getSeasonStringForURL(Season season) { public static String getSeasonStringForURL(Season season) {


+ 7
- 11
src/main/java/app/views/match/MatchView.java View File

@ -4,8 +4,8 @@ import app.data.service.ChessComService;
import app.data.service.GameInfoService; import app.data.service.GameInfoService;
import app.data.service.GameService; import app.data.service.GameService;
import app.gameimage.GameImageService; import app.gameimage.GameImageService;
import app.navigation.regular.RegularNavigationLevel;
import app.navigation.regular.RegularNavigationService;
import app.navigation.match.MatchNavigation;
import app.navigation.match.MatchNavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.match.components.MatchComponent; import app.views.match.components.MatchComponent;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;
@ -17,20 +17,16 @@ import org.springframework.beans.factory.annotation.Autowired;
@CssImport("app/views/match/match-view.css") @CssImport("app/views/match/match-view.css")
@Route(value = "match", layout = MainView.class) @Route(value = "match", layout = MainView.class)
@PageTitle("Schachliga DACH - Results - Matches") @PageTitle("Schachliga DACH - Results - Matches")
public class MatchView extends NavigationViewBase {
public class MatchView extends NavigationViewBase<MatchNavigation> {
private final ChessComService chessComService; private final ChessComService chessComService;
private final GameService gameService;
private final GameInfoService gameInfoService;
private final GameImageService gameImageService; private final GameImageService gameImageService;
private MatchComponent matchComponent; private MatchComponent matchComponent;
public MatchView(@Autowired RegularNavigationService regularNavigationService,
@Autowired ChessComService chessComService, @Autowired GameService gameService, GameInfoService gameInfoService, GameImageService gameImageService) {
super(regularNavigationService, "match", RegularNavigationLevel.MATCH);
public MatchView(@Autowired MatchNavigationService matchNavigationService,
@Autowired ChessComService chessComService, GameImageService gameImageService) {
super(matchNavigationService, "match");
this.chessComService = chessComService; this.chessComService = chessComService;
this.gameService = gameService;
this.gameInfoService = gameInfoService;
this.gameImageService = gameImageService; this.gameImageService = gameImageService;
addClassName("match-view"); addClassName("match-view");
@ -43,7 +39,7 @@ public class MatchView extends NavigationViewBase {
//////////// ////////////
private void configureLayout() { private void configureLayout() {
matchComponent = new MatchComponent(navigation, chessComService, gameImageService);
matchComponent = new MatchComponent((MatchNavigation) navigation, chessComService, gameImageService);
add(matchComponent); add(matchComponent);
} }


+ 7
- 7
src/main/java/app/views/match/components/EditMatchCard.java View File

@ -5,7 +5,7 @@ import app.data.entity.Match;
import app.data.service.ChessComService; import app.data.service.ChessComService;
import app.data.service.MatchService; import app.data.service.MatchService;
import app.gameimage.GameImageService; import app.gameimage.GameImageService;
import app.navigation.regular.RegularNavigation;
import app.navigation.match.MatchNavigation;
import app.utils.ChessComUtils; import app.utils.ChessComUtils;
import app.utils.ComponentUtils; import app.utils.ComponentUtils;
import app.utils.MatchUtils; import app.utils.MatchUtils;
@ -28,7 +28,7 @@ import static com.vaadin.flow.component.button.ButtonVariant.LUMO_PRIMARY;
public class EditMatchCard extends VerticalLayout { public class EditMatchCard extends VerticalLayout {
private final RegularNavigation regularNavigation;
private final MatchNavigation matchNavigation;
private final MatchService matchService; private final MatchService matchService;
private final ChessComService chessComService; private final ChessComService chessComService;
private final GameImageService gameImageService; private final GameImageService gameImageService;
@ -48,10 +48,10 @@ public class EditMatchCard extends VerticalLayout {
private Match match; private Match match;
public EditMatchCard(RegularNavigation regularNavigation, ChessComService chessComService, GameImageService gameImageService) {
this.regularNavigation = regularNavigation;
public EditMatchCard(MatchNavigation matchNavigation, ChessComService chessComService, GameImageService gameImageService) {
this.matchNavigation = matchNavigation;
this.chessComService = chessComService; this.chessComService = chessComService;
this.matchService = regularNavigation.getMatchService();
this.matchService = matchNavigation.getMatchService();
this.gameImageService = gameImageService; this.gameImageService = gameImageService;
defineLayout(); defineLayout();
@ -167,7 +167,7 @@ public class EditMatchCard extends VerticalLayout {
matchService.update(match); matchService.update(match);
match.getGames().forEach(gameImageService::createImageIfNotPresent); match.getGames().forEach(gameImageService::createImageIfNotPresent);
regularNavigation.setEditFlag(false);
matchNavigation.setEditFlag(false);
}; };
} }
@ -192,6 +192,6 @@ public class EditMatchCard extends VerticalLayout {
} }
private ComponentEventListener<ClickEvent<Button>> createEditCancelButtonListener() { private ComponentEventListener<ClickEvent<Button>> createEditCancelButtonListener() {
return event -> UI.getCurrent().navigate(String.format("matchday/%s", regularNavigation.getWildcardParam().replace("edit/", "")));
return event -> UI.getCurrent().navigate(String.format("matchday/%s", matchNavigation.getWildcardParam().replace("edit/", "")));
} }
} }

+ 11
- 11
src/main/java/app/views/match/components/MatchComponent.java View File

@ -6,7 +6,7 @@ import app.data.entity.Match;
import app.data.service.ChessComService; import app.data.service.ChessComService;
import app.data.service.MatchService; import app.data.service.MatchService;
import app.gameimage.GameImageService; import app.gameimage.GameImageService;
import app.navigation.regular.RegularNavigation;
import app.navigation.match.MatchNavigation;
import app.utils.ComponentUtils; import app.utils.ComponentUtils;
import app.utils.StringUtils; import app.utils.StringUtils;
import app.views.navigation.interfaces.ContentConfigurable; import app.views.navigation.interfaces.ContentConfigurable;
@ -26,7 +26,7 @@ import java.util.NoSuchElementException;
public class MatchComponent extends Div implements ContentConfigurable { public class MatchComponent extends Div implements ContentConfigurable {
private final RegularNavigation regularNavigation;
private final MatchNavigation matchNavigation;
private final MatchService matchService; private final MatchService matchService;
private final GameImageService gameImageService; private final GameImageService gameImageService;
@ -43,14 +43,14 @@ public class MatchComponent extends Div implements ContentConfigurable {
private Match match; private Match match;
private CalculatedMatch calculatedMatch; private CalculatedMatch calculatedMatch;
public MatchComponent(RegularNavigation regularNavigation,
public MatchComponent(MatchNavigation matchNavigation,
@Autowired ChessComService chessComService, @Autowired ChessComService chessComService,
@Autowired GameImageService gameImageService) { @Autowired GameImageService gameImageService) {
this.regularNavigation = regularNavigation;
this.matchService = regularNavigation.getMatchService();
this.matchNavigation = matchNavigation;
this.matchService = matchNavigation.getMatchService();
this.gameImageService = gameImageService; this.gameImageService = gameImageService;
this.editMatchCard = new EditMatchCard(regularNavigation, chessComService, gameImageService);
this.editMatchCard = new EditMatchCard(matchNavigation, chessComService, gameImageService);
defineLayout(); defineLayout();
} }
@ -95,7 +95,7 @@ public class MatchComponent extends Div implements ContentConfigurable {
Button button = new Button("Add games", new Icon(VaadinIcon.PLUS)); Button button = new Button("Add games", new Icon(VaadinIcon.PLUS));
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> { button.addClickListener(event -> {
regularNavigation.setEditFlag(true);
matchNavigation.setEditFlag(true);
remove(noGamesLayout); remove(noGamesLayout);
}); });
return button; return button;
@ -113,13 +113,13 @@ public class MatchComponent extends Div implements ContentConfigurable {
@Override @Override
public void configureContent() { public void configureContent() {
try { try {
match = regularNavigation.getSelectedMatch().orElseThrow();
match = matchNavigation.getSelectedMatch().orElseThrow();
calculatedMatch = matchService.getCalculatedMatch(match); calculatedMatch = matchService.getCalculatedMatch(match);
configureHeaderContent(); configureHeaderContent();
configureMainContent(); configureMainContent();
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
gamesLayout.removeAll(); gamesLayout.removeAll();
add(regularNavigation.getValidationLabel());
add(matchNavigation.getValidationLabel());
} }
} }
@ -138,7 +138,7 @@ public class MatchComponent extends Div implements ContentConfigurable {
} }
private void configureHeaderResultLabel() { private void configureHeaderResultLabel() {
if (match.getGames().isEmpty() || regularNavigation.editFlag()) {
if (match.getGames().isEmpty() || matchNavigation.editFlag()) {
headerLayout.remove(headerResultLabel); headerLayout.remove(headerResultLabel);
} else { } else {
headerLayout.add(headerResultLabel); headerLayout.add(headerResultLabel);
@ -148,7 +148,7 @@ public class MatchComponent extends Div implements ContentConfigurable {
} }
private void configureMainContent() { private void configureMainContent() {
if (regularNavigation.editFlag()) {
if (matchNavigation.editFlag()) {
remove(gamesLayout); remove(gamesLayout);
add(editLayout); add(editLayout);
editMatchCard.configureContent(match); editMatchCard.configureContent(match);


+ 9
- 8
src/main/java/app/views/matchday/MatchdayView.java View File

@ -1,7 +1,8 @@
package app.views.matchday; package app.views.matchday;
import app.navigation.regular.RegularNavigationLevel;
import app.navigation.regular.RegularNavigationService;
import app.navigation.match.MatchNavigation;
import app.navigation.matchday.MatchdayNavigation;
import app.navigation.matchday.MatchdayNavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.matchday.components.MatchdayCard; import app.views.matchday.components.MatchdayCard;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;
@ -13,24 +14,24 @@ import org.springframework.beans.factory.annotation.Autowired;
@CssImport("app/views/matchday/matchday-view.css") @CssImport("app/views/matchday/matchday-view.css")
@Route(value = "matchday", layout = MainView.class) @Route(value = "matchday", layout = MainView.class)
@PageTitle("Schachliga DACH - Results - Matchdays") @PageTitle("Schachliga DACH - Results - Matchdays")
public class MatchdayView extends NavigationViewBase {
public class MatchdayView extends NavigationViewBase<MatchdayNavigation> {
private MatchdayCard matchdayCard; private MatchdayCard matchdayCard;
public MatchdayView(@Autowired RegularNavigationService regularNavigationService) {
super(regularNavigationService, "matchday", RegularNavigationLevel.MATCHDAY);
public MatchdayView(@Autowired MatchdayNavigationService matchNavigationService) {
super(matchNavigationService, "matchday");
addClassName("matchday-view"); addClassName("matchday-view");
configureLayout();
defineLayout();
} }
//////////// ////////////
// LAYOUT // // LAYOUT //
//////////// ////////////
private void configureLayout() {
matchdayCard = new MatchdayCard(navigation);
private void defineLayout() {
matchdayCard = new MatchdayCard((MatchdayNavigation) navigation);
add(matchdayCard); add(matchdayCard);
} }


+ 12
- 11
src/main/java/app/views/matchday/components/MatchdayCard.java View File

@ -2,9 +2,10 @@ package app.views.matchday.components;
import app.data.bean.CalculatedMatch; import app.data.bean.CalculatedMatch;
import app.data.entity.Matchday; import app.data.entity.Matchday;
import app.navigation.regular.RegularNavigation;
import app.navigation.regular.components.button.NextMatchdayButton;
import app.navigation.regular.components.button.PrevMatchdayButton;
import app.navigation.match.MatchNavigation;
import app.navigation.matchday.MatchdayNavigation;
import app.navigation.matchday.components.button.NextMatchdayButton;
import app.navigation.matchday.components.button.PrevMatchdayButton;
import app.utils.ComponentUtils; import app.utils.ComponentUtils;
import app.utils.EntityStringUtils; import app.utils.EntityStringUtils;
import app.utils.StringUtils; import app.utils.StringUtils;
@ -28,7 +29,7 @@ import java.util.NoSuchElementException;
public class MatchdayCard extends Div implements ContentConfigurable { public class MatchdayCard extends Div implements ContentConfigurable {
private final RegularNavigation regularNavigation;
private final MatchdayNavigation matchdayNavigation;
private final Calendar calendar = Calendar.getInstance(); private final Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM."); SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.");
@ -38,8 +39,8 @@ public class MatchdayCard extends Div implements ContentConfigurable {
private final Grid<CalculatedMatch> grid = new Grid<>(); private final Grid<CalculatedMatch> grid = new Grid<>();
public MatchdayCard(RegularNavigation regularNavigation) {
this.regularNavigation = regularNavigation;
public MatchdayCard(MatchdayNavigation matchdayNavigation) {
this.matchdayNavigation = matchdayNavigation;
addClassName("card"); addClassName("card");
add(new VerticalLayout(header, grid)); add(new VerticalLayout(header, grid));
@ -55,7 +56,7 @@ public class MatchdayCard extends Div implements ContentConfigurable {
} }
private void defineHeader() { private void defineHeader() {
header.add(new PrevMatchdayButton(this.regularNavigation), headerLabelLayout, new NextMatchdayButton(this.regularNavigation));
header.add(new PrevMatchdayButton(this.matchdayNavigation), headerLabelLayout, new NextMatchdayButton(this.matchdayNavigation));
header.setWidthFull(); header.setWidthFull();
headerLabelLayout.addClassName("matchday-header-label-layout"); headerLabelLayout.addClassName("matchday-header-label-layout");
@ -107,7 +108,7 @@ public class MatchdayCard extends Div implements ContentConfigurable {
Button button = new Button(); Button button = new Button();
button.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE); button.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
String seasonAndMatchdayParam = regularNavigation.getWildcardParam();
String seasonAndMatchdayParam = matchdayNavigation.getWildcardParam();
String matchParam = EntityStringUtils.getMatchStringForURL(match.getMatch()); String matchParam = EntityStringUtils.getMatchStringForURL(match.getMatch());
String targetWildcardParam = String.format("match/%s%s/", seasonAndMatchdayParam, matchParam); String targetWildcardParam = String.format("match/%s%s/", seasonAndMatchdayParam, matchParam);
@ -129,12 +130,12 @@ public class MatchdayCard extends Div implements ContentConfigurable {
@Override @Override
public void configureContent() { public void configureContent() {
try { try {
Matchday matchday = regularNavigation.getSelectedMatchday().orElseThrow();
Matchday matchday = matchdayNavigation.getSelectedMatchday().orElseThrow();
configureHeaderLabels(matchday); configureHeaderLabels(matchday);
grid.setItems(regularNavigation.getMatchService().getCalculatedMatches(matchday));
grid.setItems(matchdayNavigation.getMatchdayService().getCalculatedMatches(matchday));
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
removeAll(); removeAll();
add(regularNavigation.getValidationLabel());
add(matchdayNavigation.getValidationLabel());
} }
} }


+ 3
- 18
src/main/java/app/views/navigation/NavigationViewBase.java View File

@ -3,12 +3,7 @@ package app.views.navigation;
import app.navigation.AbstractNavigationHeader; import app.navigation.AbstractNavigationHeader;
import app.navigation.Navigation; import app.navigation.Navigation;
import app.navigation.NavigationService; import app.navigation.NavigationService;
import app.navigation.regular.RegularNavigation;
import app.navigation.regular.RegularNavigationLevel;
import app.navigation.regular.RegularNavigationService;
import app.navigation.regular.components.RegularNavigationHeader;
import com.vaadin.flow.component.orderedlayout.FlexComponent; 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.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.HasUrlParameter;
@ -20,25 +15,15 @@ public abstract class NavigationViewBase<T extends Navigation> extends VerticalL
protected final Navigation navigation; protected final Navigation navigation;
protected final AbstractNavigationHeader<T> navigationHeader; protected final AbstractNavigationHeader<T> navigationHeader;
protected NavigationViewBase(@Autowired NavigationService<T> navigationService,
String route,
RegularNavigationLevel regularNavigationLevel) {
@SuppressWarnings("unchecked")
protected NavigationViewBase(@Autowired NavigationService<T> navigationService, String route) {
this.navigation = navigationService.getNewNavigation(); this.navigation = navigationService.getNewNavigation();
navigation.setRoute(route); navigation.setRoute(route);
if (navigation instanceof RegularNavigation) {
((RegularNavigation) navigation).setNavigationLevel(regularNavigationLevel);
}
this.navigationHeader = new RegularNavigationHeader(navigation);
this.navigationHeader = navigationService.getNewNavigationHeader((T) navigation);
define(); define();
} }
protected NavigationViewBase(@Autowired RegularNavigationService regularNavigationService,
String route) {
this(regularNavigationService, route, null);
}
private void define() { private void define() {
add(navigationHeader); add(navigationHeader);
addClassName("content"); addClassName("content");


+ 8
- 7
src/main/java/app/views/table/TableView.java View File

@ -1,8 +1,9 @@
package app.views.table; package app.views.table;
import app.data.service.PlayerService; import app.data.service.PlayerService;
import app.navigation.regular.RegularNavigationLevel;
import app.navigation.regular.RegularNavigationService;
import app.navigation.match.MatchNavigationService;
import app.navigation.matchday.MatchdayNavigation;
import app.navigation.matchday.MatchdayNavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;
import app.views.table.components.TableCard; import app.views.table.components.TableCard;
@ -16,18 +17,18 @@ import org.springframework.beans.factory.annotation.Autowired;
@Route(value = "table", layout = MainView.class) @Route(value = "table", layout = MainView.class)
@RouteAlias(value = "", layout = MainView.class) @RouteAlias(value = "", layout = MainView.class)
@PageTitle("Schachliga DACH - Table") @PageTitle("Schachliga DACH - Table")
public class TableView extends NavigationViewBase {
public class TableView extends NavigationViewBase<MatchdayNavigation> {
private final PlayerService playerService; private final PlayerService playerService;
private TableCard tableCard; private TableCard tableCard;
public TableView(@Autowired RegularNavigationService regularNavigationService,
public TableView(@Autowired MatchdayNavigationService matchdayNavigationService,
@Autowired PlayerService playerService) { @Autowired PlayerService playerService) {
super(regularNavigationService, "table", RegularNavigationLevel.MATCHDAY);
super(matchdayNavigationService, "table");
this.playerService = playerService; this.playerService = playerService;
this.navigation.setOnlyMatchdaysWithActivity(true);
((MatchdayNavigation) this.navigation).setOnlyMatchdaysWithActivity(true);
addClassName("table-view"); addClassName("table-view");
@ -39,7 +40,7 @@ public class TableView extends NavigationViewBase {
//////////// ////////////
private void defineLayout() { private void defineLayout() {
tableCard = new TableCard(navigation, playerService);
tableCard = new TableCard((MatchdayNavigation) navigation, playerService);
add(tableCard); add(tableCard);
} }


+ 10
- 9
src/main/java/app/views/table/components/TableCard.java View File

@ -3,9 +3,10 @@ package app.views.table.components;
import app.data.bean.PlayerForTable; import app.data.bean.PlayerForTable;
import app.data.entity.Matchday; import app.data.entity.Matchday;
import app.data.service.PlayerService; import app.data.service.PlayerService;
import app.navigation.regular.RegularNavigation;
import app.navigation.regular.components.button.NextMatchdayButton;
import app.navigation.regular.components.button.PrevMatchdayButton;
import app.navigation.match.MatchNavigation;
import app.navigation.matchday.MatchdayNavigation;
import app.navigation.matchday.components.button.NextMatchdayButton;
import app.navigation.matchday.components.button.PrevMatchdayButton;
import app.utils.ComponentUtils; import app.utils.ComponentUtils;
import app.utils.EntityStringUtils; import app.utils.EntityStringUtils;
import app.utils.StringUtils; import app.utils.StringUtils;
@ -27,7 +28,7 @@ import java.util.NoSuchElementException;
public class TableCard extends Div implements ContentConfigurable { public class TableCard extends Div implements ContentConfigurable {
private final RegularNavigation regularNavigation;
private final MatchdayNavigation matchdayNavigation;
private final PlayerService playerService; private final PlayerService playerService;
@ -35,8 +36,8 @@ public class TableCard extends Div implements ContentConfigurable {
private final HorizontalLayout headerLabelLayout = new HorizontalLayout(); private final HorizontalLayout headerLabelLayout = new HorizontalLayout();
private final Grid<PlayerForTable> grid = new Grid<>(); private final Grid<PlayerForTable> grid = new Grid<>();
public TableCard(RegularNavigation regularNavigation, @Autowired PlayerService playerService) {
this.regularNavigation = regularNavigation;
public TableCard(MatchdayNavigation matchdayNavigation, @Autowired PlayerService playerService) {
this.matchdayNavigation = matchdayNavigation;
this.playerService = playerService; this.playerService = playerService;
addClassName("card"); addClassName("card");
@ -47,7 +48,7 @@ public class TableCard extends Div implements ContentConfigurable {
} }
private void defineHeader() { private void defineHeader() {
header.add(new PrevMatchdayButton(this.regularNavigation), headerLabelLayout, new NextMatchdayButton(this.regularNavigation));
header.add(new PrevMatchdayButton(this.matchdayNavigation), headerLabelLayout, new NextMatchdayButton(this.matchdayNavigation));
header.setWidthFull(); header.setWidthFull();
headerLabelLayout.addClassName("table-header-label-layout"); headerLabelLayout.addClassName("table-header-label-layout");
@ -161,7 +162,7 @@ public class TableCard extends Div implements ContentConfigurable {
@Override @Override
public void configureContent() { public void configureContent() {
try { try {
Matchday matchday = regularNavigation.getSelectedMatchday().orElseThrow();
Matchday matchday = matchdayNavigation.getSelectedMatchday().orElseThrow();
String mainText = "Table"; String mainText = "Table";
String matchdayText = String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday)); String matchdayText = String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday));
@ -169,7 +170,7 @@ public class TableCard extends Div implements ContentConfigurable {
grid.setItems(playerService.getPlayersForTable(matchday)); grid.setItems(playerService.getPlayersForTable(matchday));
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
removeAll(); removeAll();
add(regularNavigation.getValidationLabel());
add(matchdayNavigation.getValidationLabel());
} }
} }
} }

Loading…
Cancel
Save