diff --git a/frontend/app/views/about/about-view.css b/frontend/app/views/example/about/about-view.css
similarity index 100%
rename from frontend/app/views/about/about-view.css
rename to frontend/app/views/example/about/about-view.css
diff --git a/frontend/app/views/addressform/address-form-view.css b/frontend/app/views/example/addressform/address-form-view.css
similarity index 100%
rename from frontend/app/views/addressform/address-form-view.css
rename to frontend/app/views/example/addressform/address-form-view.css
diff --git a/frontend/app/views/cardlist/card-list-view.css b/frontend/app/views/example/cardlist/card-list-view.css
similarity index 100%
rename from frontend/app/views/cardlist/card-list-view.css
rename to frontend/app/views/example/cardlist/card-list-view.css
diff --git a/frontend/app/views/creditcardform/credit-card-form-view.css b/frontend/app/views/example/creditcardform/credit-card-form-view.css
similarity index 100%
rename from frontend/app/views/creditcardform/credit-card-form-view.css
rename to frontend/app/views/example/creditcardform/credit-card-form-view.css
diff --git a/frontend/app/views/helloworld/hello-world-view.css b/frontend/app/views/example/helloworld/hello-world-view.css
similarity index 100%
rename from frontend/app/views/helloworld/hello-world-view.css
rename to frontend/app/views/example/helloworld/hello-world-view.css
diff --git a/frontend/app/views/map/map-view.css b/frontend/app/views/example/map/map-view.css
similarity index 100%
rename from frontend/app/views/map/map-view.css
rename to frontend/app/views/example/map/map-view.css
diff --git a/frontend/app/views/masterdetail/master-detail-view.css b/frontend/app/views/example/masterdetail/master-detail-view.css
similarity index 100%
rename from frontend/app/views/masterdetail/master-detail-view.css
rename to frontend/app/views/example/masterdetail/master-detail-view.css
diff --git a/frontend/app/views/personform/person-form-view.css b/frontend/app/views/example/personform/person-form-view.css
similarity index 100%
rename from frontend/app/views/personform/person-form-view.css
rename to frontend/app/views/example/personform/person-form-view.css
diff --git a/frontend/app/views/main/main-view.css b/frontend/app/views/main/main-view.css
index 14c6eed..a355ce4 100644
--- a/frontend/app/views/main/main-view.css
+++ b/frontend/app/views/main/main-view.css
@@ -1,3 +1,31 @@
+
+/*/////////*/
+/* GENERAL */
+/*/////////*/
+
+.content {
+ background-color: var(--lumo-contrast-10pct);
+ min-height: 100%;
+}
+
+.grid-wrapper {
+ background-color: var(--lumo-base-color);
+ border-radius: var(--lumo-border-radius);
+ box-shadow: var(--lumo-box-shadow-xs);
+ padding: 0 var(--lumo-space-m) var(--lumo-space-m);
+}
+
+.wrapper {
+ background-color: var(--lumo-base-color);
+ border-radius: var(--lumo-border-radius);
+ box-shadow: var(--lumo-box-shadow-xs);
+ padding: var(--lumo-space-m);
+}
+
+/*//////////////////*/
+/* APP-LAYOUT-STUFF */
+/*//////////////////*/
+
#header {
height: var(--lumo-size-xl);
box-shadow: var(--lumo-box-shadow-s);
diff --git a/frontend/app/views/match/match-view.css b/frontend/app/views/match/match-view.css
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/app/views/results/results-view.css b/frontend/app/views/matchday/matchday-view.css
similarity index 60%
rename from frontend/app/views/results/results-view.css
rename to frontend/app/views/matchday/matchday-view.css
index 42ea6ed..e0585be 100644
--- a/frontend/app/views/results/results-view.css
+++ b/frontend/app/views/matchday/matchday-view.css
@@ -1,13 +1,9 @@
-.about-view {
- display: block;
-}
-
-.column_header {
+.matchday-view .column_header {
font-weight: bold;
font-size: large;
}
-.matchday_header {
+.matchday-view .matchday_header {
font-weight: bolder;
font-size: x-large;
text-align: center;
diff --git a/frontend/app/views/table/table-view.css b/frontend/app/views/table/table-view.css
index 8143403..d045ea9 100644
--- a/frontend/app/views/table/table-view.css
+++ b/frontend/app/views/table/table-view.css
@@ -1,8 +1,4 @@
-.about-view {
- display: block;
-}
-
-.important_table_column_header {
+.table-view .important-table-column-header {
font-weight: bold;
font-size: large;
-}
+}
\ No newline at end of file
diff --git a/frontend/styles/shared-styles.js b/frontend/styles/shared-styles.js
index 4bc9f36..445e8ef 100644
--- a/frontend/styles/shared-styles.js
+++ b/frontend/styles/shared-styles.js
@@ -8,38 +8,44 @@ $_documentContainer.innerHTML = `
-
-
`;
document.head.appendChild($_documentContainer.content);
diff --git a/src/main/java/app/components/label/ValidationLabel.java b/src/main/java/app/components/label/ValidationLabel.java
new file mode 100644
index 0000000..4992c52
--- /dev/null
+++ b/src/main/java/app/components/label/ValidationLabel.java
@@ -0,0 +1,16 @@
+package app.components.label;
+
+
+import com.vaadin.flow.component.html.Label;
+
+public class ValidationLabel extends Label {
+ private boolean valid = true;
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+}
diff --git a/src/main/java/app/components/navigation/NavigationHeader.java b/src/main/java/app/components/navigation/NavigationHeader.java
new file mode 100644
index 0000000..7d92066
--- /dev/null
+++ b/src/main/java/app/components/navigation/NavigationHeader.java
@@ -0,0 +1,40 @@
+package app.components.navigation;
+
+import app.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 NavigationHeader extends HorizontalLayout {
+
+ private final Navigation navigation;
+
+ private final Label seasonLabel = new Label("Season:");
+ private final Label matchdayLabel = new Label("Matchday:");
+ private final Label matchLabel = new Label("Match:");
+
+ public NavigationHeader(Navigation navigation) {
+ this.navigation = navigation;
+ configureLayout();
+ configureChildren();
+ }
+
+ private void configureLayout() {
+ setWidthFull();
+ setAlignItems(FlexComponent.Alignment.CENTER);
+ setJustifyContentMode(FlexComponent.JustifyContentMode.END);
+ }
+
+ private void configureChildren() {
+ removeAll();
+ if (navigation.isSeasonEnabled()) {
+ add(seasonLabel, navigation.getSeasonSelect());
+ }
+ if (navigation.isMatchdayEnabled()) {
+ add(matchdayLabel, navigation.getMatchdaySelect());
+ }
+ if (navigation.isMatchEnabled()) {
+ add(matchLabel, navigation.getMatchSelect());
+ }
+ }
+}
diff --git a/src/main/java/app/components/navigation/SeasonAndMatchdayNavigation.java b/src/main/java/app/components/navigation/SeasonAndMatchdayNavigation.java
deleted file mode 100644
index 8171b2f..0000000
--- a/src/main/java/app/components/navigation/SeasonAndMatchdayNavigation.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.components.navigation;
-
-import app.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());
- }
-}
diff --git a/src/main/java/app/components/navigation/button/ButtonUtils.java b/src/main/java/app/components/navigation/button/ButtonUtils.java
new file mode 100644
index 0000000..3f03970
--- /dev/null
+++ b/src/main/java/app/components/navigation/button/ButtonUtils.java
@@ -0,0 +1,14 @@
+package app.components.navigation.button;
+
+import app.navigation.Navigation;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+class ButtonUtils {
+
+ static int getMatchdayIndex(Navigation navigation) {
+ AtomicInteger index = new AtomicInteger();
+ navigation.getSelectedMatchday().ifPresent(matchday -> index.set(navigation.getMatchdayList().indexOf(matchday)));
+ return index.get();
+ }
+}
diff --git a/src/main/java/app/components/navigation/button/NextMatchdayButton.java b/src/main/java/app/components/navigation/button/NextMatchdayButton.java
new file mode 100644
index 0000000..7b6d280
--- /dev/null
+++ b/src/main/java/app/components/navigation/button/NextMatchdayButton.java
@@ -0,0 +1,38 @@
+package app.components.navigation.button;
+
+import app.data.entity.Matchday;
+import app.navigation.Navigation;
+import com.vaadin.flow.component.button.Button;
+import com.vaadin.flow.component.icon.Icon;
+import com.vaadin.flow.component.icon.VaadinIcon;
+
+import java.util.Optional;
+
+public class NextMatchdayButton extends Button {
+
+ private final Navigation navigation;
+
+ public NextMatchdayButton(Navigation navigation) {
+ this.navigation = navigation;
+
+ if (!navigation.isMatchdayEnabled())
+ throw new IllegalStateException("Cannot instantiate NextMatchdayButton when Matchdays are not enabled!");
+
+ setIcon(new Icon(VaadinIcon.ARROW_RIGHT));
+
+ navigation.addRunnableToBeRunAfterSelection(this::configure);
+ }
+
+ private void configure() {
+ Optional nextMatchday = getNextMatchday();
+ setEnabled(nextMatchday.isPresent());
+ addClickListener(event -> nextMatchday.ifPresent(matchday -> navigation.getMatchdaySelect().setValue(matchday)));
+ }
+
+ private Optional getNextMatchday() {
+ int index = ButtonUtils.getMatchdayIndex(navigation);
+ if (index >= 0 && index < navigation.getMatchdayList().size() - 1)
+ return Optional.ofNullable(navigation.getMatchdayList().get(index + 1));
+ return Optional.empty();
+ }
+}
diff --git a/src/main/java/app/components/navigation/button/PrevMatchdayButton.java b/src/main/java/app/components/navigation/button/PrevMatchdayButton.java
new file mode 100644
index 0000000..df1af78
--- /dev/null
+++ b/src/main/java/app/components/navigation/button/PrevMatchdayButton.java
@@ -0,0 +1,37 @@
+package app.components.navigation.button;
+
+import app.data.entity.Matchday;
+import app.navigation.Navigation;
+import com.vaadin.flow.component.button.Button;
+import com.vaadin.flow.component.icon.Icon;
+import com.vaadin.flow.component.icon.VaadinIcon;
+
+import java.util.Optional;
+
+public class PrevMatchdayButton extends Button {
+
+ private final Navigation navigation;
+
+ public PrevMatchdayButton(Navigation navigation) {
+ this.navigation = navigation;
+
+ if (!navigation.isMatchdayEnabled())
+ throw new IllegalStateException("Cannot instantiate PrevMatchdayButton when Matchdays are not enabled!");
+
+ setIcon(new Icon(VaadinIcon.ARROW_LEFT));
+
+ navigation.addRunnableToBeRunAfterSelection(this::configure);
+ }
+
+ private void configure() {
+ Optional prevMatchday = getPrevMatchday();
+ setEnabled(prevMatchday.isPresent());
+ addClickListener(event -> prevMatchday.ifPresent(matchday -> navigation.getMatchdaySelect().setValue(matchday)));
+ }
+
+ private Optional getPrevMatchday() {
+ int index = ButtonUtils.getMatchdayIndex(navigation);
+ if (index > 0) return Optional.ofNullable(navigation.getMatchdayList().get(index - 1));
+ return Optional.empty();
+ }
+}
diff --git a/src/main/java/app/data/service/ChessComService.java b/src/main/java/app/data/service/ChessComService.java
index 80ce226..8c8ea25 100644
--- a/src/main/java/app/data/service/ChessComService.java
+++ b/src/main/java/app/data/service/ChessComService.java
@@ -10,13 +10,12 @@ import app.data.entity.Player;
import app.utils.ChessComUtils;
import app.utils.HttpUtils;
import com.google.gson.Gson;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import java.util.*;
-import java.util.function.Function;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
@Service
public class ChessComService {
@@ -117,26 +116,4 @@ public class ChessComService {
}
return Optional.empty();
}
-// return getArchiveUrls(player).stream()
-// .map(this::getChessComArchive)
-// .flatMap(chessComArchive -> chessComArchive.orElseThrow().getGames().stream())
-// .filter(chessComGame -> chessComGame.getUrl().equals(game.getGameInfo().getUrl()))
-// .findFirst();
-
-// .forEach(g -> g
-// .filter(chessComGame -> chessComGame.getUrl().equals(game.getGameInfo().getUrl())))
-// .findFirst();
-// }
-// private Optional getChessComGame(@NonNull Game game, Player player) {
-// if (!(game.getMatch().getPlayer1().equals(player) || game.getMatch().getPlayer2().equals(player))) {
-// throw new IllegalArgumentException("Player must be participating in Game!");
-// }
-// return getArchiveUrls(player).stream()
-// .map(this::getChessComArchive)
-// .flatMap((Function, Stream>)
-// chessComArchive -> chessComArchive.stream()
-// .flatMap(archive -> archive.getGames().stream()))
-// .filter(chessComGame -> chessComGame.getUrl().equals(game.getGameInfo().getUrl()))
-// .findFirst();
-// }
}
diff --git a/src/main/java/app/navigation/Navigation.java b/src/main/java/app/navigation/Navigation.java
index eb21db6..b2aa912 100644
--- a/src/main/java/app/navigation/Navigation.java
+++ b/src/main/java/app/navigation/Navigation.java
@@ -1,37 +1,34 @@
package app.navigation;
+import app.components.label.ValidationLabel;
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 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.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.WildcardParameter;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.lang.NonNull;
-import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class Navigation implements HasUrlParameter {
- // 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 runnablesToBeRunAfterSeasonSelection = new ArrayList<>();
- private final List runnablesToBeRunAfterMatchdaySelection = new ArrayList<>();
- private final List runnablesToBeRunAfterMatchSelection = new ArrayList<>();
+ private String route;
+ private boolean onlyMatchdaysWithActivity;
+
+ private final List runnablesToBeRunAfterSelection = new ArrayList<>();
private final SeasonService seasonService;
private final MatchdayService matchdayService;
@@ -45,113 +42,148 @@ public class Navigation implements HasUrlParameter {
private final Select matchdaySelect = new Select<>();
private final Select 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 boolean seasonEnabled = false;
+ private boolean matchdayEnabled = false;
+ private boolean matchEnabled = 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));
+ private final ValidationLabel validationLabel = new ValidationLabel();
- public Navigation(String route,
- @Autowired SeasonService seasonService,
+ public Navigation(@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 setRoute(String route) {
+ this.route = route;
+ }
+
+ public void setOnlyMatchdaysWithActivity(boolean onlyMatchdaysWithActivity) {
+ this.onlyMatchdaysWithActivity = onlyMatchdaysWithActivity;
+ }
+
+ public void setSeasonEnabled(boolean seasonEnabled) {
+ this.seasonEnabled = seasonEnabled;
+ }
+
+ public void setMatchdayEnabled(boolean matchdayEnabled) {
+ this.matchdayEnabled = matchdayEnabled;
+ }
+
+ public void setMatchEnabled(boolean matchEnabled) {
+ this.matchEnabled = matchEnabled;
+ }
+
+ public void addRunnableToBeRunAfterSelection(Runnable runnable) {
+ runnablesToBeRunAfterSelection.add(runnable);
+ }
+
+ public boolean isSeasonEnabled() {
+ return seasonEnabled;
}
- public void setAutoselectMatchday(boolean autoselectMatchday) {
- this.autoselectMatchday = autoselectMatchday;
+ public boolean isMatchdayEnabled() {
+ return matchdayEnabled;
}
- public void setAutoselectMatch(boolean autoselectMatch) {
- this.autoselectMatch = autoselectMatch;
+ public boolean isMatchEnabled() {
+ return matchEnabled;
+ }
+
+ private String getRoute() {
+ if (route != null) return route;
+ throw new IllegalStateException("Route must be set!");
}
private void updateUrl() {
+ String seasonParam = null;
+ String matchdayParam = null;
+ String matchParam = null;
+ if (seasonEnabled) seasonParam = seasonSelect.getValue().toString();
+ if (matchdayEnabled) matchdayParam = matchdaySelect.getValue().toString();
+ if (matchEnabled) matchParam = matchdaySelect.getValue().toString();
+
String params = NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam);
- UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", route, params));
+ UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params));
}
-
private HasValue.ValueChangeListener super AbstractField.ComponentValueChangeEvent