From ca14661ae9b69bc8a69b82807f2b4e1bee118fb2 Mon Sep 17 00:00:00 2001 From: GAM Date: Sat, 27 Mar 2021 10:21:58 +0100 Subject: [PATCH] Dates for Matchdays, Table-Formatting --- db/db_increment_001.sql | 17 ++++---- db/db_increment_002.sql | 5 +++ frontend/app/views/main/main-view.css | 2 +- frontend/app/views/matchday/matchday-view.css | 8 ++-- frontend/app/views/table/table-view.css | 8 +++- src/main/java/app/data/entity/Season.java | 20 +++++++++ .../app/data/service/MatchdayService.java | 9 ++-- src/main/java/app/navigation/Navigation.java | 2 +- src/main/java/app/utils/ComponentUtils.java | 30 +++++++++++++ .../java/app/utils/EntityComponentUtils.java | 18 -------- .../views/match/components/EditMatchCard.java | 9 ++-- .../match/components/MatchComponent.java | 6 +-- .../match/components/utils/GameCardUtils.java | 4 +- .../matchday/components/MatchdayCard.java | 43 ++++++++++++++++--- .../app/views/table/components/TableCard.java | 23 +++++++++- 15 files changed, 146 insertions(+), 58 deletions(-) create mode 100644 db/db_increment_002.sql create mode 100644 src/main/java/app/utils/ComponentUtils.java delete mode 100644 src/main/java/app/utils/EntityComponentUtils.java diff --git a/db/db_increment_001.sql b/db/db_increment_001.sql index c59caf1..b6b9bf5 100644 --- a/db/db_increment_001.sql +++ b/db/db_increment_001.sql @@ -1,8 +1,9 @@ -ALTER TABLE "game_info" ADD COLUMN "pgn" varchar; -ALTER TABLE "game_info" ADD COLUMN "rated" boolean; -ALTER TABLE "game_info" ADD COLUMN "time_class" varchar; -ALTER TABLE "game_info" ADD COLUMN "rules" varchar; -ALTER TABLE "game_info" ADD COLUMN "white_rating" int; -ALTER TABLE "game_info" ADD COLUMN "black_rating" int; -ALTER TABLE "game_info" ADD COLUMN "white_result" varchar; -ALTER TABLE "game_info" ADD COLUMN "black_result" varchar; \ No newline at end of file +ALTER TABLE "game_info" + ADD COLUMN "pgn" varchar, + ADD COLUMN "rated" boolean, + ADD COLUMN "time_class" varchar, + ADD COLUMN "rules" varchar, + ADD COLUMN "white_rating" int, + ADD COLUMN "black_rating" int, + ADD COLUMN "white_result" varchar, + ADD COLUMN "black_result" varchar; \ No newline at end of file diff --git a/db/db_increment_002.sql b/db/db_increment_002.sql new file mode 100644 index 0000000..6876a29 --- /dev/null +++ b/db/db_increment_002.sql @@ -0,0 +1,5 @@ +ALTER TABLE "season" + ADD COLUMN "week_of_first_matchday" int not null default 9 CHECK ( week_of_first_matchday > 0 AND week_of_first_matchday <= 53 ), + ADD COLUMN "first_weekday_of_matchday" int not null default 2 CHECK ( first_weekday_of_matchday > 0 AND first_weekday_of_matchday <= 7 ), + ADD COLUMN "last_weekday_of_matchday" int not null default 1 CHECK ( last_weekday_of_matchday > 0 AND last_weekday_of_matchday <= 7 ), + ADD COLUMN "weekday_of_view_change" int not null default 4 CHECK ( weekday_of_view_change > 0 AND weekday_of_view_change <= 7 ); diff --git a/frontend/app/views/main/main-view.css b/frontend/app/views/main/main-view.css index 55afd3a..b68d659 100644 --- a/frontend/app/views/main/main-view.css +++ b/frontend/app/views/main/main-view.css @@ -25,7 +25,7 @@ font-weight: bold; } -.nickname-label { +.parentheses-label { margin-left: var(--lumo-space-xs); } diff --git a/frontend/app/views/matchday/matchday-view.css b/frontend/app/views/matchday/matchday-view.css index e1ca104..9bb760e 100644 --- a/frontend/app/views/matchday/matchday-view.css +++ b/frontend/app/views/matchday/matchday-view.css @@ -3,9 +3,9 @@ font-size: large; } -.matchday-view .matchday-header-label { +.matchday-view .matchday-header-label-layout { width: 100%; - font-weight: bolder; + justify-content: center; font-size: x-large; - text-align: center; -} \ No newline at end of file +} + diff --git a/frontend/app/views/table/table-view.css b/frontend/app/views/table/table-view.css index d045ea9..da08625 100644 --- a/frontend/app/views/table/table-view.css +++ b/frontend/app/views/table/table-view.css @@ -1,4 +1,10 @@ .table-view .important-table-column-header { font-weight: bold; font-size: large; -} \ No newline at end of file +} + +.table-view .table-header-label-layout { + width: 100%; + justify-content: center; + font-size: x-large; +} diff --git a/src/main/java/app/data/entity/Season.java b/src/main/java/app/data/entity/Season.java index 4b1f5a4..af9817d 100644 --- a/src/main/java/app/data/entity/Season.java +++ b/src/main/java/app/data/entity/Season.java @@ -24,6 +24,26 @@ public class Season extends AbstractEntity { nullable = false) private Integer yearEnd; + @Basic + @Column(name = "week_of_first_matchday", + nullable = false) + private Integer weekOfFirstMatchday; + + @Basic + @Column(name = "first_weekday_of_matchday", + nullable = false) + private Integer firstWeekdayOfMatchday; + + @Basic + @Column(name = "last_weekday_of_matchday", + nullable = false) + private Integer lastWeekdayOfMatchday; + + @Basic + @Column(name = "weekday_of_view_change", + nullable = false) + private Integer weekdayOfViewChange; + @OneToMany(mappedBy = "season", cascade = CascadeType.ALL, orphanRemoval = true) diff --git a/src/main/java/app/data/service/MatchdayService.java b/src/main/java/app/data/service/MatchdayService.java index e1b06d8..4448e61 100644 --- a/src/main/java/app/data/service/MatchdayService.java +++ b/src/main/java/app/data/service/MatchdayService.java @@ -52,12 +52,9 @@ public class MatchdayService extends CrudService { .collect(Collectors.toList()); } - public Optional getLastMatchdayWithActivityOrElseFirstMatchday(@NonNull Season season) { - List matchdaysWithActivity = getMatchdaysWithActivitySorted(season); - if (matchdaysWithActivity.isEmpty()) { - return getFirstMatchday(season); - } - return Optional.of(matchdaysWithActivity.get(matchdaysWithActivity.size() - 1)); + public List getMatchdaysWithActivitySortedOrElseListWithOnlyFirstMatchday(@NonNull Season season) { + List matchdaysWithActivitySorted = getMatchdaysWithActivitySorted(season); + return matchdaysWithActivitySorted.isEmpty() ? List.of(getFirstMatchday(season).orElseThrow()) : matchdaysWithActivitySorted; } public boolean hasActivity(@NonNull Matchday matchday) { diff --git a/src/main/java/app/navigation/Navigation.java b/src/main/java/app/navigation/Navigation.java index 4ac86a5..855c49b 100644 --- a/src/main/java/app/navigation/Navigation.java +++ b/src/main/java/app/navigation/Navigation.java @@ -196,7 +196,7 @@ public class Navigation implements HasUrlParameter { private void fillMatchdaySelectWithData(Season season) { matchdayList.clear(); List matchdaysToAdd = onlyMatchdaysWithActivity ? - matchdayService.getMatchdaysWithActivitySorted(season) : matchdayService.getMatchdaysSorted(season); + matchdayService.getMatchdaysWithActivitySortedOrElseListWithOnlyFirstMatchday(season) : matchdayService.getMatchdaysSorted(season); matchdayList.addAll(matchdaysToAdd); matchdaySelect.setItems(matchdayList); } diff --git a/src/main/java/app/utils/ComponentUtils.java b/src/main/java/app/utils/ComponentUtils.java new file mode 100644 index 0000000..5669b0d --- /dev/null +++ b/src/main/java/app/utils/ComponentUtils.java @@ -0,0 +1,30 @@ +package app.utils; + +import app.data.entity.Player; +import com.vaadin.flow.component.html.Label; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; + +public class ComponentUtils { + private ComponentUtils() { + } + + public static HorizontalLayout getPlayerLabel(Player player) { + return getFormattedLabelWithParentheses(player.getName(), player.getNickname()); + } + + public static HorizontalLayout getFormattedLabelWithParentheses(String mainText, String textInParentheses) { + HorizontalLayout horizontalLayout = new HorizontalLayout(); + configureFormattedLabelWithParentheses(horizontalLayout, mainText, textInParentheses); + return horizontalLayout; + } + + public static void configureFormattedLabelWithParentheses(HorizontalLayout horizontalLayout, String mainText, String textInParentheses) { + Label mainLabel = new Label(mainText); + mainLabel.addClassName("bold-label"); + Label parenthesesLabel = new Label(String.format("(%s)", textInParentheses)); + parenthesesLabel.addClassName("parentheses-label"); + + horizontalLayout.removeAll(); + horizontalLayout.add(mainLabel, parenthesesLabel); + } +} diff --git a/src/main/java/app/utils/EntityComponentUtils.java b/src/main/java/app/utils/EntityComponentUtils.java deleted file mode 100644 index 4f7c4fc..0000000 --- a/src/main/java/app/utils/EntityComponentUtils.java +++ /dev/null @@ -1,18 +0,0 @@ -package app.utils; - -import app.data.entity.Player; -import com.vaadin.flow.component.html.Label; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; - -public class EntityComponentUtils { - private EntityComponentUtils() { - } - - public static HorizontalLayout getPlayerLabel(Player player) { - Label name = new Label(player.getName()); - name.addClassName("bold-label"); - Label nickname = new Label(String.format("(%s)", player.getNickname())); - nickname.addClassName("nickname-label"); - return new HorizontalLayout(name, nickname); - } -} diff --git a/src/main/java/app/views/match/components/EditMatchCard.java b/src/main/java/app/views/match/components/EditMatchCard.java index 69763bb..202bfa7 100644 --- a/src/main/java/app/views/match/components/EditMatchCard.java +++ b/src/main/java/app/views/match/components/EditMatchCard.java @@ -7,6 +7,7 @@ import app.data.service.MatchService; import app.gameimage.GameImageService; import app.navigation.Navigation; import app.utils.ChessComUtils; +import app.utils.ComponentUtils; import app.utils.MatchUtils; import app.utils.TimeControl; import com.vaadin.flow.component.ClickEvent; @@ -85,11 +86,9 @@ public class EditMatchCard extends VerticalLayout { TextField textField = new TextField(); textField.setWidth("23em"); textField.setPlaceholder("Please enter URL"); - Label gameLabel = new Label(String.format("Game %d", startGameNumber + i)); - gameLabel.addClassName("bold-label"); - Label timeControlLabel = new Label(String.format("(%s):", timeControl.toPresentationString())); - timeControlLabel.addClassName("nickname-label"); - HorizontalLayout labelLayout = new HorizontalLayout(gameLabel, timeControlLabel); + String gameString = String.format("Game %d", startGameNumber + i); + String timeControlString = timeControl.toPresentationString(); + HorizontalLayout labelLayout = ComponentUtils.getFormattedLabelWithParentheses(gameString, timeControlString); labelLayout.setSpacing(false); labelLayout.setAlignItems(Alignment.CENTER); labelLayout.setJustifyContentMode(JustifyContentMode.START); diff --git a/src/main/java/app/views/match/components/MatchComponent.java b/src/main/java/app/views/match/components/MatchComponent.java index 159e22c..16745ec 100644 --- a/src/main/java/app/views/match/components/MatchComponent.java +++ b/src/main/java/app/views/match/components/MatchComponent.java @@ -7,7 +7,7 @@ import app.data.service.ChessComService; import app.data.service.MatchService; import app.gameimage.GameImageService; import app.navigation.Navigation; -import app.utils.EntityComponentUtils; +import app.utils.ComponentUtils; import app.utils.StringUtils; import app.views.navigation.interfaces.ContentConfigurable; import com.vaadin.flow.component.button.Button; @@ -129,8 +129,8 @@ public class MatchComponent extends Div implements ContentConfigurable { } private void configureHeaderPlayersLayout() { - HorizontalLayout player1 = EntityComponentUtils.getPlayerLabel(calculatedMatch.getPlayer1()); - HorizontalLayout player2 = EntityComponentUtils.getPlayerLabel(calculatedMatch.getPlayer2()); + HorizontalLayout player1 = ComponentUtils.getPlayerLabel(calculatedMatch.getPlayer1()); + HorizontalLayout player2 = ComponentUtils.getPlayerLabel(calculatedMatch.getPlayer2()); Label vs = new Label("vs."); headerPlayersLayout.removeAll(); diff --git a/src/main/java/app/views/match/components/utils/GameCardUtils.java b/src/main/java/app/views/match/components/utils/GameCardUtils.java index 57b0aeb..1e2f70b 100644 --- a/src/main/java/app/views/match/components/utils/GameCardUtils.java +++ b/src/main/java/app/views/match/components/utils/GameCardUtils.java @@ -3,7 +3,7 @@ package app.views.match.components.utils; import app.data.entity.Game; import app.data.entity.Player; import app.utils.ChessComUtils; -import app.utils.EntityComponentUtils; +import app.utils.ComponentUtils; import app.utils.TimeControl; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; @@ -44,7 +44,7 @@ public class GameCardUtils { div.addClassName("player"); div.addClassName(white ? "white-player" : "black-player"); - HorizontalLayout playerLabel = EntityComponentUtils.getPlayerLabel(player); + HorizontalLayout playerLabel = ComponentUtils.getPlayerLabel(player); playerLabel.setWidthFull(); playerLabel.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER); diff --git a/src/main/java/app/views/matchday/components/MatchdayCard.java b/src/main/java/app/views/matchday/components/MatchdayCard.java index e69903f..3e8e5e5 100644 --- a/src/main/java/app/views/matchday/components/MatchdayCard.java +++ b/src/main/java/app/views/matchday/components/MatchdayCard.java @@ -5,6 +5,7 @@ import app.data.entity.Matchday; import app.navigation.Navigation; import app.navigation.components.button.NextMatchdayButton; import app.navigation.components.button.PrevMatchdayButton; +import app.utils.ComponentUtils; import app.utils.EntityStringUtils; import app.utils.StringUtils; import app.utils.VaadinUtils; @@ -21,33 +22,43 @@ import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.NoSuchElementException; public class MatchdayCard extends Div implements ContentConfigurable { private final Navigation navigation; + private final Calendar calendar = Calendar.getInstance(); + SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM."); + private final HorizontalLayout header = new HorizontalLayout(); - private final Label headerLabel = new Label(); + private final HorizontalLayout headerLabelLayout = new HorizontalLayout(); private final Grid grid = new Grid<>(); + public MatchdayCard(Navigation navigation) { this.navigation = navigation; addClassName("card"); - VerticalLayout inner = new VerticalLayout(); - add(inner); - inner.add(header, grid); + add(new VerticalLayout(header, grid)); + + defineCalendar(); defineHeader(); defineGrid(); } + private void defineCalendar() { + calendar.setFirstDayOfWeek(Calendar.MONDAY); + } + private void defineHeader() { - header.add(new PrevMatchdayButton(this.navigation), headerLabel, new NextMatchdayButton(this.navigation)); + header.add(new PrevMatchdayButton(this.navigation), headerLabelLayout, new NextMatchdayButton(this.navigation)); header.setWidthFull(); - headerLabel.addClassName("matchday-header-label"); + headerLabelLayout.addClassName("matchday-header-label-layout"); } @@ -119,11 +130,29 @@ public class MatchdayCard extends Div implements ContentConfigurable { public void configureContent() { try { Matchday matchday = navigation.getSelectedMatchday().orElseThrow(); - headerLabel.setText(String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday))); // TODO: add dates + configureHeaderLabels(matchday); grid.setItems(navigation.getMatchService().getCalculatedMatches(matchday)); } catch (NoSuchElementException e) { removeAll(); add(navigation.getValidationLabel()); } } + + private void configureHeaderLabels(Matchday matchday) { + int week = matchday.getSeason().getWeekOfFirstMatchday() + matchday.getNumber() - 1; + int firstDay = matchday.getSeason().getFirstWeekdayOfMatchday(); + int lastDay = matchday.getSeason().getLastWeekdayOfMatchday(); + + calendar.set(Calendar.WEEK_OF_YEAR, week); + + calendar.set(Calendar.DAY_OF_WEEK, firstDay); + String startDate = dateFormat.format(calendar.getTime()); + + calendar.set(Calendar.DAY_OF_WEEK, lastDay); + String endDate = dateFormat.format(calendar.getTime()); + + String mainText = String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday)); + String dateText = String.format("%s - %s", startDate, endDate); + ComponentUtils.configureFormattedLabelWithParentheses(headerLabelLayout, mainText, dateText); + } } diff --git a/src/main/java/app/views/table/components/TableCard.java b/src/main/java/app/views/table/components/TableCard.java index 16d954e..7465dd7 100644 --- a/src/main/java/app/views/table/components/TableCard.java +++ b/src/main/java/app/views/table/components/TableCard.java @@ -4,6 +4,10 @@ import app.data.bean.PlayerForTable; import app.data.entity.Matchday; import app.data.service.PlayerService; import app.navigation.Navigation; +import app.navigation.components.button.NextMatchdayButton; +import app.navigation.components.button.PrevMatchdayButton; +import app.utils.ComponentUtils; +import app.utils.EntityStringUtils; import app.utils.StringUtils; import app.utils.VaadinUtils; import app.views.navigation.interfaces.ContentConfigurable; @@ -16,6 +20,7 @@ import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; import org.springframework.beans.factory.annotation.Autowired; import java.util.NoSuchElementException; @@ -26,18 +31,28 @@ public class TableCard extends Div implements ContentConfigurable { private final PlayerService playerService; + private final HorizontalLayout header = new HorizontalLayout(); + private final HorizontalLayout headerLabelLayout = new HorizontalLayout(); private final Grid grid = new Grid<>(); public TableCard(Navigation navigation, @Autowired PlayerService playerService) { this.navigation = navigation; this.playerService = playerService; - addClassName("grid-card"); - add(grid); + addClassName("card"); + add(new VerticalLayout(header, grid)); + defineHeader(); defineGrid(); } + private void defineHeader() { + header.add(new PrevMatchdayButton(this.navigation), headerLabelLayout, new NextMatchdayButton(this.navigation)); + header.setWidthFull(); + + headerLabelLayout.addClassName("table-header-label-layout"); + } + private void defineGrid() { // TODO: rounded corners for rows? @@ -147,6 +162,10 @@ public class TableCard extends Div implements ContentConfigurable { public void configureContent() { try { Matchday matchday = navigation.getSelectedMatchday().orElseThrow(); + + String mainText = "Table"; + String matchdayText = String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday)); + ComponentUtils.configureFormattedLabelWithParentheses(headerLabelLayout, mainText, matchdayText); grid.setItems(playerService.getPlayersForTable(matchday)); } catch (NoSuchElementException e) { removeAll();