From ebb307143d9ea7771dffb891a0ad6d85a646e803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kollonay=20Zolt=C3=A1n?= <116440323+kz44@users.noreply.github.com> Date: Sat, 13 Apr 2024 10:28:50 +0200 Subject: [PATCH 1/2] UserDTO from the me endpoint has wrong list of sports (#70) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Frnka --- .../sportsmatch/services/UserServiceImp.java | 21 +++++++++++-------- .../services/UserServiceImpTest.java | 13 ++++++------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/backend/sportsmatch/src/main/java/com/sportsmatch/services/UserServiceImp.java b/backend/sportsmatch/src/main/java/com/sportsmatch/services/UserServiceImp.java index f0c838b4..61ffbd53 100644 --- a/backend/sportsmatch/src/main/java/com/sportsmatch/services/UserServiceImp.java +++ b/backend/sportsmatch/src/main/java/com/sportsmatch/services/UserServiceImp.java @@ -1,13 +1,13 @@ package com.sportsmatch.services; +import com.sportsmatch.dtos.SportDTO; import com.sportsmatch.dtos.UserDTO; +import com.sportsmatch.dtos.UserInfoDTO; import com.sportsmatch.mappers.SportMapper; import com.sportsmatch.mappers.UserMapper; import com.sportsmatch.models.*; import com.sportsmatch.repositories.SportRepository; import com.sportsmatch.repositories.UserRepository; -import com.sportsmatch.dtos.SportDTO; -import com.sportsmatch.dtos.UserInfoDTO; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -16,13 +16,11 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; + import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; @Service @RequiredArgsConstructor @@ -69,16 +67,21 @@ public UserDTO getUserById(Long id) { throw new ResponseStatusException(HttpStatus.NOT_FOUND); } + Set sportUsers = user.get().getSportUsers(); + + List userSports = sportUsers.stream() + .map(SportUser::getSport) + .map(sportMapper::toDTO) + .toList(); + List events = new ArrayList<>(user.get().getEventsPlayed()); - List sports = new ArrayList<>(); for (EventPlayer e : events) { rankService.updatePlayersRanks(e.getEvent()); - sports.add(sportMapper.toDTO(e.getEvent().getSport())); } return UserDTO.builder() .name(user.get().getName()) - .sports(sports) + .sports(userSports) .elo(user.get().getRank()) .win(user.get().getWin()) .loss(user.get().getLoss()) diff --git a/backend/sportsmatch/src/test/java/com/sportsmatch/services/UserServiceImpTest.java b/backend/sportsmatch/src/test/java/com/sportsmatch/services/UserServiceImpTest.java index c875c297..81f8f0ec 100644 --- a/backend/sportsmatch/src/test/java/com/sportsmatch/services/UserServiceImpTest.java +++ b/backend/sportsmatch/src/test/java/com/sportsmatch/services/UserServiceImpTest.java @@ -106,7 +106,7 @@ void getUserById() { Sport sport = new Sport(); sport.setId(1L); sport.setName("Tennis"); - sport.setEmoji("🎾"); + sport.setEmoji(""); sport.setBackgroundImageURL("./assets/sport-component-tennis.png"); // SportUser @@ -125,17 +125,16 @@ void getUserById() { sports.add(sportDTO); // Event - Event event = mock(Event.class); + Event event = new Event(); event.setSport(sport); - EventPlayer eventPlayer = mock(EventPlayer.class); - - when(eventPlayer.getEvent()).thenReturn(event); - when(eventPlayer.getEvent().getSport()).thenReturn(sport); + // EventPlayer (no need to mock) + EventPlayer eventPlayer = new EventPlayer(); + eventPlayer.setEvent(event); // Set the event directly user.getEventsPlayed().add(eventPlayer); - doNothing().when(rankService).updatePlayersRanks(event); + // No need to mock eventPlayer.getEvent() UserDTO expectedUserDTO = UserDTO.builder().name(user.getName()).elo(user.getRank()).sports(sports).build(); From 36e0a0cd84bd02aaae2281ca26ad438b19fc85c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kollonay=20Zolt=C3=A1n?= <116440323+kz44@users.noreply.github.com> Date: Sat, 13 Apr 2024 10:48:28 +0200 Subject: [PATCH 2/2] SMA-87-Add Annotation to the Pageable object (#64) --- .../controllers/EventsController.java | 10 ++--- .../controllers/SportController.java | 3 +- .../repositories/EventRepository.java | 2 +- .../sportsmatch/services/EventService.java | 4 +- frontend/sportsmatch-app/package-lock.json | 43 +++---------------- .../src/generated/api/index.ts | 1 - .../src/generated/api/models/Pageable.ts | 10 ----- .../api/services/EventsControllerService.ts | 13 ++++-- .../api/services/SportControllerService.ts | 13 ++++-- frontend/sportsmatch-app/src/pages/Index.tsx | 4 +- 10 files changed, 38 insertions(+), 65 deletions(-) delete mode 100644 frontend/sportsmatch-app/src/generated/api/models/Pageable.ts diff --git a/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/EventsController.java b/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/EventsController.java index 0bf39aca..fc73f0ad 100644 --- a/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/EventsController.java +++ b/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/EventsController.java @@ -45,7 +45,7 @@ public ResponseEntity deleteEvent(@PathVariable("id") Long id) { } @GetMapping("/upcoming-events") - public ResponseEntity getUpcomingEvents(@RequestParam List sportsIds) { + public ResponseEntity getUpcomingEvents(@RequestBody List sportsIds) { List listOfEvents = eventService.getEventsBySports(sportsIds); return ResponseEntity.ok().body(listOfEvents); } @@ -70,8 +70,8 @@ public List getEventsHistory(@ParameterObject final Pageable pa * @return a list of Events sorted by distance from the given location. User can filter by sports. */ @GetMapping("/nearby") - public List getNearbyEvents(@RequestParam RequestEventDTO requestEventDTO, - final Pageable pageable) { + public List getNearbyEvents(@RequestBody RequestEventDTO requestEventDTO, + @ParameterObject final Pageable pageable) { return eventService.getNearbyEvents(requestEventDTO, pageable); } @@ -91,7 +91,7 @@ public ResponseEntity joinEvent(@PathVariable("id") Long id) { * @return a list of logged-in user's upcoming EventDTOs ordered by date ascending */ @GetMapping("/upcoming-matches") - public List getUpcomingMatches(@ParameterObject final Pageable pageable) { - return eventService.getUsersUpcomingEvents(pageable); + public List getUpcomingMatches() { + return eventService.getUsersUpcomingEvents(); } } diff --git a/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/SportController.java b/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/SportController.java index 58eea7e8..98299148 100644 --- a/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/SportController.java +++ b/backend/sportsmatch/src/main/java/com/sportsmatch/controllers/SportController.java @@ -3,6 +3,7 @@ import com.sportsmatch.dtos.SportDTO; import com.sportsmatch.services.SportService; import lombok.RequiredArgsConstructor; +import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,7 +25,7 @@ public class SportController { * @return paginated list of SportDTO */ @GetMapping("/all") - public List getSports(final Pageable pageable) { + public List getSports(@ParameterObject final Pageable pageable) { return sportService.getAllSports(pageable); } } diff --git a/backend/sportsmatch/src/main/java/com/sportsmatch/repositories/EventRepository.java b/backend/sportsmatch/src/main/java/com/sportsmatch/repositories/EventRepository.java index 7f6f89d2..857477ff 100644 --- a/backend/sportsmatch/src/main/java/com/sportsmatch/repositories/EventRepository.java +++ b/backend/sportsmatch/src/main/java/com/sportsmatch/repositories/EventRepository.java @@ -32,7 +32,7 @@ List findEventsByUser( @Param("id") Long id, @Param("now") LocalDateTime now, Pageable pageable); @Query("SELECT ep.event FROM EventPlayer ep WHERE ep.player.id = :id AND ep.event.dateStart > :now ORDER BY ep.event.dateEnd ASC") - List findUpcomingEventsByUser(@Param("id") Long id, @Param("now") LocalDateTime now, Pageable pageable); + List findUpcomingEventsByUser(@Param("id") Long id, @Param("now") LocalDateTime now); diff --git a/backend/sportsmatch/src/main/java/com/sportsmatch/services/EventService.java b/backend/sportsmatch/src/main/java/com/sportsmatch/services/EventService.java index 42ec53dc..a92072be 100644 --- a/backend/sportsmatch/src/main/java/com/sportsmatch/services/EventService.java +++ b/backend/sportsmatch/src/main/java/com/sportsmatch/services/EventService.java @@ -208,10 +208,10 @@ public List getNearbyEvents(RequestEventDTO requestEventDTO, final Pag * * @return a list of logged-in user's upcoming EventDTOs ordered by date ascending */ - public List getUsersUpcomingEvents(Pageable pageable) { + public List getUsersUpcomingEvents() { User loggedUser = userService.getUserFromContext(); return eventRepository - .findUpcomingEventsByUser(loggedUser.getId(), LocalDateTime.now(), pageable) + .findUpcomingEventsByUser(loggedUser.getId(), LocalDateTime.now()) .stream() .map(eventMapper::convertEventToEventDTO) .collect(Collectors.toList()); diff --git a/frontend/sportsmatch-app/package-lock.json b/frontend/sportsmatch-app/package-lock.json index 9eb97062..3aaf5a18 100644 --- a/frontend/sportsmatch-app/package-lock.json +++ b/frontend/sportsmatch-app/package-lock.json @@ -8,7 +8,6 @@ "name": "sportsmatch-app", "version": "0.0.0", "dependencies": { - "axios": "^1.6.7", "bootstrap": "^5.3.2", "react": "^18.2.0", "react-bootstrap": "^2.10.0", @@ -2391,7 +2390,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -2405,16 +2405,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2663,6 +2653,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2858,6 +2849,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -3854,25 +3846,6 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3886,6 +3859,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5285,6 +5259,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -5293,6 +5268,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -5896,11 +5872,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/frontend/sportsmatch-app/src/generated/api/index.ts b/frontend/sportsmatch-app/src/generated/api/index.ts index e4e996a1..286286a7 100644 --- a/frontend/sportsmatch-app/src/generated/api/index.ts +++ b/frontend/sportsmatch-app/src/generated/api/index.ts @@ -10,7 +10,6 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { AuthRequestDTO } from './models/AuthRequestDTO'; export type { EventDTO } from './models/EventDTO'; export { EventHistoryDTO } from './models/EventHistoryDTO'; -export type { Pageable } from './models/Pageable'; export type { PlaceDTO } from './models/PlaceDTO'; export type { RatingDTO } from './models/RatingDTO'; export type { RequestEventDTO } from './models/RequestEventDTO'; diff --git a/frontend/sportsmatch-app/src/generated/api/models/Pageable.ts b/frontend/sportsmatch-app/src/generated/api/models/Pageable.ts deleted file mode 100644 index e7e40e89..00000000 --- a/frontend/sportsmatch-app/src/generated/api/models/Pageable.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type Pageable = { - page?: number; - size?: number; - sort?: Array; -}; - diff --git a/frontend/sportsmatch-app/src/generated/api/services/EventsControllerService.ts b/frontend/sportsmatch-app/src/generated/api/services/EventsControllerService.ts index bb4b26f0..4152f418 100644 --- a/frontend/sportsmatch-app/src/generated/api/services/EventsControllerService.ts +++ b/frontend/sportsmatch-app/src/generated/api/services/EventsControllerService.ts @@ -4,7 +4,6 @@ /* eslint-disable */ import type { EventDTO } from '../models/EventDTO'; import type { EventHistoryDTO } from '../models/EventHistoryDTO'; -import type { Pageable } from '../models/Pageable'; import type { RequestEventDTO } from '../models/RequestEventDTO'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -101,20 +100,26 @@ export class EventsControllerService { } /** * @param requestEventDto - * @param pageable + * @param page Zero-based page index (0..N) + * @param size The size of the page to be returned + * @param sort Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported. * @returns EventDTO OK * @throws ApiError */ public static getNearbyEvents( requestEventDto: RequestEventDTO, - pageable: Pageable, + page?: number, + size: number = 20, + sort?: Array, ): CancelablePromise> { return __request(OpenAPI, { method: 'GET', url: '/api/v1/event/nearby', query: { 'requestEventDTO': requestEventDto, - 'pageable': pageable, + 'page': page, + 'size': size, + 'sort': sort, }, }); } diff --git a/frontend/sportsmatch-app/src/generated/api/services/SportControllerService.ts b/frontend/sportsmatch-app/src/generated/api/services/SportControllerService.ts index ecb9c2fc..8b035721 100644 --- a/frontend/sportsmatch-app/src/generated/api/services/SportControllerService.ts +++ b/frontend/sportsmatch-app/src/generated/api/services/SportControllerService.ts @@ -2,25 +2,30 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { Pageable } from '../models/Pageable'; import type { SportDTO } from '../models/SportDTO'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; export class SportControllerService { /** - * @param pageable + * @param page Zero-based page index (0..N) + * @param size The size of the page to be returned + * @param sort Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported. * @returns SportDTO OK * @throws ApiError */ public static getSports( - pageable: Pageable, + page?: number, + size: number = 20, + sort?: Array, ): CancelablePromise> { return __request(OpenAPI, { method: 'GET', url: '/api/v1/sports/all', query: { - 'pageable': pageable, + 'page': page, + 'size': size, + 'sort': sort, }, }); } diff --git a/frontend/sportsmatch-app/src/pages/Index.tsx b/frontend/sportsmatch-app/src/pages/Index.tsx index 1bb7f56d..72a42a30 100644 --- a/frontend/sportsmatch-app/src/pages/Index.tsx +++ b/frontend/sportsmatch-app/src/pages/Index.tsx @@ -59,7 +59,9 @@ export default function MainPage() { } const response = await EventsControllerService.getNearbyEvents( requestEventDTO, - {}, + 0, + 20, + undefined, ) if (!Array.isArray(response)) { throw new Error('Failed to fetch event data')