From fb84ec1cd504747f023757e3a6f9df721fe2f3f6 Mon Sep 17 00:00:00 2001 From: Software Magico Date: Sun, 5 May 2024 19:16:23 +0200 Subject: [PATCH 1/4] SonarQube fixes --- .gitignore | 3 ++- README.md | 2 +- .../kt/core/controller/RankingController.java | 10 +++++----- .../kt/core/providers/RankingProvider.java | 16 +++++++++++++--- .../kt/rest/services/RankingServices.java | 15 +++++++++++---- .../src/main/resources/application.properties | 13 ++++++------- .../competitors-ranking.component.html | 3 +++ .../competitors-ranking.component.scss | 10 +++++++++- .../competitors-ranking.component.ts | 9 +++++++++ .../competitors-ranking.module.ts | 14 ++++++++++++-- .../tournament-brackets-editor.component.ts | 2 +- frontend/src/app/services/ranking.service.ts | 12 +++++++++--- .../participant-list.component.ts | 2 +- frontend/src/assets/i18n/ca.json | 3 ++- frontend/src/assets/i18n/de.json | 3 ++- frontend/src/assets/i18n/en.json | 3 ++- frontend/src/assets/i18n/es.json | 3 ++- frontend/src/assets/i18n/it.json | 3 ++- frontend/src/assets/i18n/nl.json | 3 ++- 19 files changed, 94 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 2332a06e4..47fca8951 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ default_data.sql .attach_* .env_bak target/* -*.properties_bak \ No newline at end of file +*.properties_bak +*.properties.mysql \ No newline at end of file diff --git a/README.md b/README.md index f9f7e886e..81813147a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager) [![GitHub last commit](https://img.shields.io/github/last-commit/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager) [![CircleCI](https://circleci.com/gh/softwaremagico/KendoTournamentManager.svg?style=shield)](https://circleci.com/gh/softwaremagico/KendoTournamentManager) -[![Time](https://img.shields.io/badge/development-603h-blueviolet.svg)]() +[![Time](https://img.shields.io/badge/development-604.5h-blueviolet.svg)]() [![Powered by](https://img.shields.io/badge/powered%20by%20java-orange.svg?logo=OpenJDK&logoColor=white)]() [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=kendo-tournament-backend&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=kendo-tournament-backend) diff --git a/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/RankingController.java b/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/RankingController.java index 9bfad1598..00b500745 100644 --- a/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/RankingController.java +++ b/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/RankingController.java @@ -262,20 +262,20 @@ public List getCompetitorsGlobalScoreRankingByClub(Integer final List competitorRoles = roleProvider.get(participants, RoleType.COMPETITOR); participants.retainAll(competitorRoles.stream().map(Role::getParticipant).collect(Collectors.toSet())); return getCompetitorsGlobalScoreRanking(participantConverter.convertAll(participants.stream() - .map(participant -> new ParticipantConverterRequest(participant, clubConverter.convert(new ClubConverterRequest(club)))).toList())); + .map(participant -> new ParticipantConverterRequest(participant, clubConverter.convert(new ClubConverterRequest(club)))).toList()), null); } - public List getCompetitorsGlobalScoreRanking(Collection competitors) { - return getCompetitorsGlobalScoreRanking(competitors, ScoreType.DEFAULT); + public List getCompetitorsGlobalScoreRanking(Collection competitors, Integer fromNumberOfDays) { + return getCompetitorsGlobalScoreRanking(competitors, ScoreType.DEFAULT, fromNumberOfDays); } - public List getCompetitorsGlobalScoreRanking(Collection competitors, ScoreType scoreType) { + public List getCompetitorsGlobalScoreRanking(Collection competitors, ScoreType scoreType, Integer fromNumberOfDays) { final Map clubsById = competitors.stream() .map(ParticipantDTO::getClub).collect(Collectors.toMap(ClubDTO::getId, Function.identity(), (r1, r2) -> r1)); return scoreOfCompetitorConverter.convertAll(rankingProvider.getCompetitorsGlobalScoreRanking( participantConverter.reverseAll(competitors), - scoreType + scoreType, fromNumberOfDays ) .stream().map(scoreOfCompetitor -> new ScoreOfCompetitorConverterRequest(scoreOfCompetitor, clubsById.get(scoreOfCompetitor.getCompetitor().getClub().getId()))).toList()); diff --git a/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/providers/RankingProvider.java b/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/providers/RankingProvider.java index 2851f849d..a23b70a53 100644 --- a/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/providers/RankingProvider.java +++ b/backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/providers/RankingProvider.java @@ -49,6 +49,8 @@ import com.softwaremagico.kt.persistence.values.TournamentType; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -206,13 +208,21 @@ public List getCompetitorGlobalRanking(ScoreType scoreType) { return scores; } - public List getCompetitorsGlobalScoreRanking(Collection competitors, ScoreType scoreType) { + public List getCompetitorsGlobalScoreRanking(Collection competitors, ScoreType scoreType, Integer fromNumberOfDays) { if (competitors == null || competitors.isEmpty()) { competitors = participantProvider.getAll(); } + //Get number since when is read the data. + final LocalDateTime from = fromNumberOfDays != null && fromNumberOfDays != 0 ? LocalDate.now().minusDays(fromNumberOfDays).atStartOfDay() : null; final List scores = new ArrayList<>(); - final List fights = fightProvider.getBy(competitors); - final List unties = duelProvider.getUnties(competitors); + final List fights = fightProvider.getBy(competitors).stream().filter(fight -> + from == null || fight.getCreatedAt().isAfter(from)).toList(); + final List unties = duelProvider.getUnties(competitors).stream().filter(duel -> + from == null || duel.getCreatedAt().isAfter(from)).toList(); + + final Set participantsInFights = fights.stream().flatMap(fight -> fight.getTeam1().getMembers().stream()).collect(Collectors.toSet()); + participantsInFights.addAll(fights.stream().flatMap(fight -> fight.getTeam2().getMembers().stream()).collect(Collectors.toSet())); + competitors.retainAll(participantsInFights); for (final Participant competitor : competitors) { scores.add(new ScoreOfCompetitor(competitor, fights, unties, false)); } diff --git a/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java b/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java index fac2785b0..93c6ecffa 100644 --- a/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java +++ b/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java @@ -53,6 +53,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; @@ -60,6 +61,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Optional; import java.util.Set; @RestController @@ -113,11 +115,13 @@ public List getCompetitorsScoreRankingTournament(@Paramete @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth")) @PostMapping(value = "/competitors", produces = MediaType.APPLICATION_JSON_VALUE) - public List getCompetitorsGlobalScoreRanking(@RequestBody(required = false) Set participants, + public List getCompetitorsGlobalScoreRanking(@RequestParam(name = "from") Optional from, + @RequestBody(required = false) Set participants, HttpServletRequest request) { - return rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>()); + return rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>(), from.orElse(null)); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_PARTICIPANT')") @Operation(summary = "Gets participant global ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/competitors/{competitorId}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -125,12 +129,15 @@ public CompetitorRanking getCompetitorsRanking(@PathVariable("competitorId") Int return rankingController.getCompetitorRanking(participantController.get(competitorId)); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth")) @PostMapping(value = "/competitors/pdf", produces = MediaType.APPLICATION_JSON_VALUE) - public byte[] getCompetitorsGlobalScoreRankingAsPdf(@RequestBody(required = false) Set participants, + public byte[] getCompetitorsGlobalScoreRankingAsPdf(@RequestParam(name = "from") Optional from, + @RequestBody(required = false) Set participants, Locale locale, HttpServletResponse response, HttpServletRequest request) { - final List scores = rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>()); + final List scores = rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>(), + from.orElse(null)); try { final ContentDisposition contentDisposition = ContentDisposition.builder("attachment") .filename("competitors score.pdf").build(); diff --git a/backend/kendo-tournament-rest/src/main/resources/application.properties b/backend/kendo-tournament-rest/src/main/resources/application.properties index ed3f037d0..64928f6fe 100644 --- a/backend/kendo-tournament-rest/src/main/resources/application.properties +++ b/backend/kendo-tournament-rest/src/main/resources/application.properties @@ -18,13 +18,12 @@ spring.messages.basename=language/language #Database Access spring.jpa.open-in-view=false -spring.kendo.datasource.jpa.hibernate.ddl-auto=update -spring.kendo.datasource.platform=mysql -spring.usermanager.datasource.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect -spring.usermanager.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.kendo.datasource.jdbc-url=jdbc:mysql://localhost:3306/kendotournament?useSSL=false&autoReconnect=true -spring.kendo.datasource.username=user -spring.kendo.datasource.password=asd123 +spring.kendo.datasource.jpa.hibernate.ddl-auto=create-drop +spring.kendo.datasource.platform=h2 +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.kendo.datasource.jdbc-url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false +spring.kendo.datasource.username=sa +spring.kendo.datasource.password= spring.kendo.datasource.initialize=true spring.kendo.datasource.test-while-idle=true diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html index f6e64509d..2ce7bc563 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html @@ -1,5 +1,8 @@
+ diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss index 350be56a9..9cfeed2fd 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss @@ -1,4 +1,5 @@ .table-container { + position: relative; overflow: auto; max-height: 70vh; } @@ -9,7 +10,7 @@ } .competitor-ranking-table { - margin: 2vw; + margin: 2vw -190px 2vm 2vm; } .competitor-ranking-table thead th { @@ -58,3 +59,10 @@ display: flex; justify-content: center; } + +.days-selector { + position: absolute; + top: 0; + right: 16px; + width: 200px; +} diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts index 3bb11ac86..ea8ae3ce7 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts @@ -22,6 +22,7 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O club: Club | undefined; competitor: Participant | undefined; showIndex: boolean | undefined; + numberOfDays: number | undefined; constructor(public dialogRef: MatDialogRef, @Inject(DOCUMENT) document: Document, @@ -40,6 +41,10 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O } ngOnInit(): void { + this.getRanking(); + } + + getRanking(): void { if (this.club?.id) { this.rankingService.getCompetitorsScoreRankingByClub(this.club.id).subscribe((competitorsScore: ScoreOfCompetitor[]): void => { this.competitorsScore = competitorsScore; @@ -102,4 +107,8 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O row.scrollIntoView({behavior: 'smooth'}); } } + + daysChanged(): void { + + } } diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.module.ts b/frontend/src/app/components/competitors-ranking/competitors-ranking.module.ts index 0e4fd9811..388cb2635 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.module.ts +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.module.ts @@ -7,6 +7,10 @@ import {MatIconModule} from "@angular/material/icon"; import {RbacModule} from "../../pipes/rbac-pipe/rbac.module"; import {MatDialogModule} from "@angular/material/dialog"; import {MatButtonModule} from "@angular/material/button"; +import {FormsModule, ReactiveFormsModule} from "@angular/forms"; +import {MatInputModule} from "@angular/material/input"; +import {MatTooltipModule} from "@angular/material/tooltip"; +import {MatSlideToggleModule} from "@angular/material/slide-toggle"; @NgModule({ @@ -18,7 +22,13 @@ import {MatButtonModule} from "@angular/material/button"; MatIconModule, RbacModule, MatDialogModule, - MatButtonModule + MatButtonModule, + FormsModule, + MatInputModule, + MatTooltipModule, + ReactiveFormsModule, + MatSlideToggleModule ] }) -export class CompetitorsRankingModule { } +export class CompetitorsRankingModule { +} diff --git a/frontend/src/app/components/tournament-brackets-editor/tournament-brackets-editor.component.ts b/frontend/src/app/components/tournament-brackets-editor/tournament-brackets-editor.component.ts index f86977a1f..77e3607a1 100644 --- a/frontend/src/app/components/tournament-brackets-editor/tournament-brackets-editor.component.ts +++ b/frontend/src/app/components/tournament-brackets-editor/tournament-brackets-editor.component.ts @@ -113,7 +113,7 @@ export class TournamentBracketsEditorComponent implements OnChanges, OnInit, OnD ngOnChanges(changes: SimpleChanges): void { this.systemOverloadService.isBusy.next(true); - if (changes['tournament'] && this.tournament != undefined) { + if (changes['tournament']) { this.updateData(true); } } diff --git a/frontend/src/app/services/ranking.service.ts b/frontend/src/app/services/ranking.service.ts index 0404602ff..a0b792bfb 100644 --- a/frontend/src/app/services/ranking.service.ts +++ b/frontend/src/app/services/ranking.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {HttpClient, HttpHeaders} from "@angular/common/http"; +import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http"; import {EnvironmentService} from "../environment.service"; import {MessageService} from "./message.service"; import {LoggerService} from "./logger.service"; @@ -68,10 +68,16 @@ export class RankingService { ); } - getCompetitorsGlobalScoreRanking(participants: Participant[] | undefined): Observable { + getCompetitorsGlobalScoreRanking(participants: Participant[] | undefined, fromDays: number | undefined): Observable { this.systemOverloadService.isBusy.next(true); const url: string = `${this.baseUrl}` + '/competitors'; - return this.http.post(url, participants) + return this.http.post(url, participants, { + params: new HttpParams({ + fromObject: { + 'from': fromDays ? fromDays : 0, + } + }) + }) .pipe( tap({ next: () => this.loggerService.info(`getting competitors ranking`), diff --git a/frontend/src/app/views/participant-list/participant-list.component.ts b/frontend/src/app/views/participant-list/participant-list.component.ts index 412ef3e7e..c52d66c5e 100644 --- a/frontend/src/app/views/participant-list/participant-list.component.ts +++ b/frontend/src/app/views/participant-list/participant-list.component.ts @@ -46,7 +46,7 @@ export class ParticipantListComponent extends RbacBasedComponent implements OnIn } ngOnInit(): void { - this.clubService.getAll().subscribe(clubs => { + this.clubService.getAll().subscribe((clubs: Club[]): void => { this.clubs = clubs }); this.showAllElements(); diff --git a/frontend/src/assets/i18n/ca.json b/frontend/src/assets/i18n/ca.json index 9083dfd6b..4116148d1 100644 --- a/frontend/src/assets/i18n/ca.json +++ b/frontend/src/assets/i18n/ca.json @@ -870,7 +870,8 @@ "achievementAllGenerated": "Un total de {{achievementsNumber}} èxits han estat generats en {{tournamentNumber}} tornejos.", "shiaijoFinished": "Tots els partits del shiaijo {{shiaijoName}} han acabat.", "userAdminGenerated": "Usuari {{userName}} ha estar creat!" - } + }, + "daysFrom": "Aplica només aquests dies" } diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json index f3bb6a22d..9b9fe40da 100644 --- a/frontend/src/assets/i18n/de.json +++ b/frontend/src/assets/i18n/de.json @@ -858,7 +858,8 @@ "achievementAllGenerated": "Insgesamt wurden {{achievementsNumber}} Erfolge in {{tournamentNumber}} Turnieren erzielt.", "shiaijoFinished": "Alle Spiele von Shiaijo {{shiaijoName}} sind beendet.", "userAdminGenerated": "Benutzer {{userName}} wurde erstellt!" - } + }, + "daysFrom": "" } diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index 1183d28e8..a76d3a08e 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -881,6 +881,7 @@ "achievementAllGenerated": "A total of {{achievementsNumber}} achievements have been generated for {{tournamentNumber}} tournaments.", "shiaijoFinished": "All shiaijo {{shiaijoName}} matches have ended.", "userAdminGenerated": "User {{userName}} has been created!" - } + }, + "daysFrom": "Apply only these days" } diff --git a/frontend/src/assets/i18n/es.json b/frontend/src/assets/i18n/es.json index 5f84827f1..a05b3823e 100644 --- a/frontend/src/assets/i18n/es.json +++ b/frontend/src/assets/i18n/es.json @@ -883,5 +883,6 @@ "achievementAllGenerated": "Un total de {{achievementsNumber}} logros han sido generados en {{tournamentNumber}} torneos.", "shiaijoFinished": "Todos los partidos del shiaijo {{shiaijoName}} han acabado.", "userAdminGenerated": "Usuario {{userName}} ha sido creado!" - } + }, + "daysFrom": "Aplica solo estos días" } diff --git a/frontend/src/assets/i18n/it.json b/frontend/src/assets/i18n/it.json index 59503a4d1..f16a16b4d 100644 --- a/frontend/src/assets/i18n/it.json +++ b/frontend/src/assets/i18n/it.json @@ -864,7 +864,8 @@ "achievementAllGenerated": "Un totale di {{achievementsNumber}} obiettivi sono stati generati in {{tournamentNumber}} tornei.", "shiaijoFinished": "Tutte le partite di shiaijo {{shiaijoName}} sono terminate.", "userAdminGenerated": "L'utente {{userName}} è stato creato!" - } + }, + "daysFrom": "22 / 5.000\nResultados de traducción\nResultado de traducción\nApplicare solo in questi giorni" } diff --git a/frontend/src/assets/i18n/nl.json b/frontend/src/assets/i18n/nl.json index 8483a8ded..2fc51a503 100644 --- a/frontend/src/assets/i18n/nl.json +++ b/frontend/src/assets/i18n/nl.json @@ -858,7 +858,8 @@ "achievementAllGenerated": "Er zijn in totaal {{achievementsNumber}} prestaties gegenereerd in {{tournamentNumber}} toernooien.", "shiaijoFinished": "Alle wedstrijden van shiaijo {{shiaijoName}} zijn afgelopen.", "userAdminGenerated": "Gebruiker {{userName}} is aangemaakt!" - } + }, + "daysFrom": "Bewerben Sie sich nur noch an diesen Tagen" } From 93dec33bf413c5d2bae642bff29e75dbdc1f3baa Mon Sep 17 00:00:00 2001 From: Software Magico Date: Sun, 5 May 2024 20:12:51 +0200 Subject: [PATCH 2/4] Generating statistics only on last X days --- .../competitors-ranking.component.ts | 6 ++-- frontend/src/app/services/ranking.service.ts | 31 ++++++++++++------- .../tournament-teams.component.ts | 2 +- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts index ea8ae3ce7..0b6f94f54 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.ts @@ -54,7 +54,7 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O this.competitorsScore = competitorsScore; }); } else { - this.rankingService.getCompetitorsGlobalScoreRanking(undefined).subscribe((competitorsScore: ScoreOfCompetitor[]): void => { + this.rankingService.getCompetitorsGlobalScoreRanking(undefined, this.numberOfDays).subscribe((competitorsScore: ScoreOfCompetitor[]): void => { this.competitorsScore = competitorsScore; //Timeout to scroll after the component is drawn. setTimeout((): void => { @@ -90,7 +90,7 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O anchor.click(); }); } else { - this.rankingService.getCompetitorsGlobalScoreRankingAsPdf(undefined).subscribe((pdf: Blob): void => { + this.rankingService.getCompetitorsGlobalScoreRankingAsPdf(undefined, this.numberOfDays).subscribe((pdf: Blob): void => { const blob: Blob = new Blob([pdf], {type: 'application/pdf'}); const downloadURL: string = window.URL.createObjectURL(blob); @@ -109,6 +109,6 @@ export class CompetitorsRankingComponent extends RbacBasedComponent implements O } daysChanged(): void { - + this.getRanking(); } } diff --git a/frontend/src/app/services/ranking.service.ts b/frontend/src/app/services/ranking.service.ts index a0b792bfb..ca28a97e7 100644 --- a/frontend/src/app/services/ranking.service.ts +++ b/frontend/src/app/services/ranking.service.ts @@ -88,21 +88,30 @@ export class RankingService { ); } - getCompetitorsGlobalScoreRankingAsPdf(participants: Participant[] | undefined): Observable { + getCompetitorsGlobalScoreRankingAsPdf(participants: Participant[] | undefined, fromDays: number | undefined): Observable { this.systemOverloadService.isBusy.next(true); const url: string = `${this.baseUrl}` + '/competitors/pdf'; - return this.http.post(url, participants, { - responseType: 'blob' as 'json', observe: 'body', headers: new HttpHeaders({ + + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' - }) - }).pipe( - tap({ - next: () => this.loggerService.info(`getting competitors ranking as pdf`), - error: () => this.systemOverloadService.isBusy.next(false), - complete: () => this.systemOverloadService.isBusy.next(false), }), - catchError(this.messageService.handleError(`getting competitors ranking as pdf`)) - ); + params: new HttpParams({ + fromObject: { + 'from': fromDays ? fromDays : 0, + } + }) + }; + + return this.http.post(url, participants, httpOptions) + .pipe( + tap({ + next: () => this.loggerService.info(`getting competitors ranking as pdf`), + error: () => this.systemOverloadService.isBusy.next(false), + complete: () => this.systemOverloadService.isBusy.next(false), + }), + catchError(this.messageService.handleError(`getting competitors ranking as pdf`)) + ); } getCompetitorsScoreRankingByClub(clubId: number): Observable { diff --git a/frontend/src/app/views/tournament-list/tournament-teams/tournament-teams.component.ts b/frontend/src/app/views/tournament-list/tournament-teams/tournament-teams.component.ts index a16cd3569..76a5d04b7 100644 --- a/frontend/src/app/views/tournament-list/tournament-teams/tournament-teams.component.ts +++ b/frontend/src/app/views/tournament-list/tournament-teams/tournament-teams.component.ts @@ -381,7 +381,7 @@ export class TournamentTeamsComponent extends RbacBasedComponent implements OnIn let participants: Participant[]; participants = [...Array.prototype.concat.apply([], [...this.members.values()]), ...this.userListData.participants]; - this.rankingService.getCompetitorsGlobalScoreRanking(participants).subscribe((_scoreRanking: ScoreOfCompetitor[]): void => { + this.rankingService.getCompetitorsGlobalScoreRanking(participants, undefined).subscribe((_scoreRanking: ScoreOfCompetitor[]): void => { for (let team of this.teams) { team.members = []; for (let i = 0; i < (this.tournament.teamSize ? this.tournament.teamSize : 1); i++) { From fbadf68a01c884ee4110fe8df291f328bd61ca5b Mon Sep 17 00:00:00 2001 From: Software Magico Date: Sun, 5 May 2024 20:38:19 +0200 Subject: [PATCH 3/4] Fixed competitor list pdf --- .gitignore | 3 ++- .../src/main/resources/language/language.properties | 4 ++-- .../main/resources/language/language_ca.properties | 4 ++-- .../main/resources/language/language_de.properties | 4 ++-- .../main/resources/language/language_es.properties | 4 ++-- .../main/resources/language/language_it.properties | 4 ++-- .../main/resources/language/language_nl.properties | 4 ++-- .../kt/rest/services/RankingServices.java | 11 +++++++++++ frontend/src/app/services/ranking.service.ts | 1 + 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 47fca8951..249a6faa9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,5 @@ default_data.sql .env_bak target/* *.properties_bak -*.properties.mysql \ No newline at end of file +*.properties.mysql +*.properties.postgres \ No newline at end of file diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language.properties index b534a798f..c956689a3 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language.properties @@ -22,8 +22,8 @@ tournament.type.championship=Championship tournament.type.tree=Tree Championship tournament.type.league=League tournament.type.loop=Loop -tournament.type.custom.championship=Custom Championship -tournament.type.king.of.the.mountain=King of the Mountain +tournament.type.custom_championship=Custom Championship +tournament.type.king_of_the_mountain=King of the Mountain tournament.type.customized=Customized club.list=Clubs list fight.list=List of fightss diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language_ca.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language_ca.properties index 470daa660..1237d9b98 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language_ca.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language_ca.properties @@ -22,8 +22,8 @@ tournament.type.championship=Campeonat tournament.type.tree=Campeonat en Arbre tournament.type.league=Lliga tournament.type.loop=Bucle -tournament.type.custom.championship=Campeonat Personalizat -tournament.type.king.of.the.mountain=Rei de la muntanya +tournament.type.custom_championship=Campeonat Personalizat +tournament.type.king_of_the_mountain=Rei de la muntanya tournament.type.customized=Personalizat club.list=Llista de clubs fight.list=Llista de partits diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language_de.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language_de.properties index 8cd92510a..1b9aa26fe 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language_de.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language_de.properties @@ -22,8 +22,8 @@ tournament.type.championship= tournament.type.tree= tournament.type.league= tournament.type.loop= -tournament.type.custom.championship= -tournament.type.king.of.the.mountain= +tournament.type.custom_championship= +tournament.type.king_of_the_mountain= tournament.type.customized= club.list=Liste der Klubs fight.list=Liste der Kämpfe diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language_es.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language_es.properties index 4ea09bfbf..7f03c8060 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language_es.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language_es.properties @@ -22,8 +22,8 @@ tournament.type.championship=Campeonato tournament.type.tree=Campeonato en Árbol tournament.type.league=Liga tournament.type.loop=Bucle -tournament.type.custom.championship=Campeonato Personalizado -tournament.type.king.of.the.mountain=Rey de la Montaña +tournament.type.custom_championship=Campeonato Personalizado +tournament.type.king_of_the_mountain=Rey de la Montaña tournament.type.customized=Personalizado club.list=Lista de clubes fight.list=Lista de partidos diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language_it.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language_it.properties index 2aba4be94..5517481e8 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language_it.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language_it.properties @@ -22,8 +22,8 @@ tournament.type.championship=Campionato tournament.type.tree=Campionato tournament.type.league=Liga tournament.type.loop=Bucle -tournament.type.custom.championship=Campionato Personalizzato -tournament.type.king.of.the.mountain=Il Re della Montagna +tournament.type.custom_championship=Campionato Personalizzato +tournament.type.king_of_the_mountain=Il Re della Montagna tournament.type.customized=Personalizzato club.list=Lista dei club fight.list=Lista degli incontri diff --git a/backend/kendo-tournament-pdf/src/main/resources/language/language_nl.properties b/backend/kendo-tournament-pdf/src/main/resources/language/language_nl.properties index b31dbffc2..541c2dabf 100644 --- a/backend/kendo-tournament-pdf/src/main/resources/language/language_nl.properties +++ b/backend/kendo-tournament-pdf/src/main/resources/language/language_nl.properties @@ -22,8 +22,8 @@ tournament.type.championship=Poule tournament.type.tree=Poule tournament.type.league=League tournament.type.loop=Loop -tournament.type.custom.championship=Custom -tournament.type.king.of.the.mountain=King of the Mountain +tournament.type.custom_championship=Custom +tournament.type.king_of_the_mountain=King of the Mountain tournament.type.customized=Custom club.list=Overzicht van de clubs fight.list=Overzicht wedstrijden diff --git a/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java b/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java index 93c6ecffa..d33c55fa5 100644 --- a/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java +++ b/backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/RankingServices.java @@ -94,6 +94,7 @@ public RankingServices(RankingController rankingController, PdfController pdfCon this.zipController = zipController; } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/competitors/groups/{groupId}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -103,6 +104,7 @@ public List getCompetitorsScoreRankingGroup(@Parameter(des return rankingController.getCompetitorsScoreRankingFromGroup(groupId); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_GUEST')") @Operation(summary = "Gets participants' ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/competitors/tournaments/{tournamentId}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -112,6 +114,7 @@ public List getCompetitorsScoreRankingTournament(@Paramete return rankingController.getCompetitorsScoreRankingFromTournament(tournamentId); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth")) @PostMapping(value = "/competitors", produces = MediaType.APPLICATION_JSON_VALUE) @@ -159,6 +162,7 @@ public List getCompetitorsGlobalScoreRanking(@Parameter(de return rankingController.getCompetitorsGlobalScoreRankingByClub(clubId); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/competitors/clubs/{clubId}/pdf", produces = MediaType.APPLICATION_JSON_VALUE) @@ -177,6 +181,7 @@ public byte[] getCompetitorsGlobalScoreRankingByClubAsPdf(@Parameter(description } } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets participants' ranking in a pdf file.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/competitors/tournaments/{tournamentId}/pdf", produces = MediaType.APPLICATION_PDF_VALUE) @@ -196,6 +201,7 @@ public byte[] getCompetitorsScoreRankingTournamentAsPdf(@Parameter(description = } } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets teams' ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/teams/groups/{groupId}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -205,6 +211,7 @@ public List getTeamsScoreRankingFromGroup(@Parameter(description return rankingController.getTeamsScoreRankingFromGroup(groupId); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_GUEST')") @Operation(summary = "Gets teams' ranking.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/teams/tournaments/{tournamentId}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -214,6 +221,7 @@ public List getTeamsScoreRankingFromTournament(@Parameter(descri return rankingController.getTeamsScoreRankingFromTournament(tournamentId); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets teams' ranking in a pdf file.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/teams/tournaments/{tournamentId}/pdf", produces = MediaType.APPLICATION_PDF_VALUE) @@ -233,6 +241,7 @@ public byte[] getTeamsScoreRankingFromTournamentAsPdf(@Parameter(description = " } } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets teams' ranking in a pdf file.", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/teams/groups/{groupId}/pdf", produces = MediaType.APPLICATION_PDF_VALUE) @@ -253,6 +262,7 @@ public byte[] getTeamsScoreRankingFromGroupAsPdf(@Parameter(description = "Id of } } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Gets complete tournament summary as html", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/summary/{tournamentId}/html", produces = MediaType.TEXT_PLAIN_VALUE) @@ -267,6 +277,7 @@ public byte[] getTournamentsSummaryAsHtml(@Parameter(description = "Id of an exi return htmlController.generateBlogCode(locale, tournament).getWordpressFormat().getBytes(StandardCharsets.UTF_8); } + @PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')") @Operation(summary = "Download all files as a zip", security = @SecurityRequirement(name = "bearerAuth")) @GetMapping(value = "/tournament/{tournamentId}/zip") diff --git a/frontend/src/app/services/ranking.service.ts b/frontend/src/app/services/ranking.service.ts index ca28a97e7..531491921 100644 --- a/frontend/src/app/services/ranking.service.ts +++ b/frontend/src/app/services/ranking.service.ts @@ -93,6 +93,7 @@ export class RankingService { const url: string = `${this.baseUrl}` + '/competitors/pdf'; const httpOptions = { + responseType: 'blob' as 'json', headers: new HttpHeaders({ 'Content-Type': 'application/json' }), From ef301b2e76f3185c56357c3631ac34c708ef686b Mon Sep 17 00:00:00 2001 From: Software Magico Date: Sun, 5 May 2024 20:57:49 +0200 Subject: [PATCH 4/4] Adding button to restrict statistics days range --- README.md | 2 +- .../competitors-ranking.component.html | 10 ++++++++-- .../competitors-ranking.component.scss | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 81813147a..a112d8711 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager) [![GitHub last commit](https://img.shields.io/github/last-commit/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager) [![CircleCI](https://circleci.com/gh/softwaremagico/KendoTournamentManager.svg?style=shield)](https://circleci.com/gh/softwaremagico/KendoTournamentManager) -[![Time](https://img.shields.io/badge/development-604.5h-blueviolet.svg)]() +[![Time](https://img.shields.io/badge/development-605h-blueviolet.svg)]() [![Powered by](https://img.shields.io/badge/powered%20by%20java-orange.svg?logo=OpenJDK&logoColor=white)]() [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=kendo-tournament-backend&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=kendo-tournament-backend) diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html index 2ce7bc563..f09173c4b 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.html @@ -1,8 +1,14 @@
- + + required (keyup.enter)="daysChanged()"> + +
{{'competitorsRanking' | translate}}
diff --git a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss index 9cfeed2fd..478fc849d 100644 --- a/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss +++ b/frontend/src/app/components/competitors-ranking/competitors-ranking.component.scss @@ -65,4 +65,10 @@ top: 0; right: 16px; width: 200px; + display: flex; +} + +.day-input { + padding: 0 10px 0 0; + min-width: 0; }
{{'competitorsRanking' | translate}}