diff --git a/app/annotation-service/README.md b/app/annotation-service/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/app/annotation-service/src/main/kotlin/com/group6/annotationservice/AnnotationServiceApplication.kt b/app/annotation-service/src/main/kotlin/com/group6/annotationservice/AnnotationServiceApplication.kt index 7369e1a4..8e096f64 100644 --- a/app/annotation-service/src/main/kotlin/com/group6/annotationservice/AnnotationServiceApplication.kt +++ b/app/annotation-service/src/main/kotlin/com/group6/annotationservice/AnnotationServiceApplication.kt @@ -2,26 +2,9 @@ package com.group6.annotationservice import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication -import org.springframework.context.annotation.Bean -import org.springframework.web.servlet.config.annotation.CorsRegistry -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer @SpringBootApplication -class AnnotationServiceApplication { - @Bean - fun corsFilter(): WebMvcConfigurer { - return object : WebMvcConfigurer { - override fun addCorsMappings(registry: CorsRegistry) { - registry.addMapping("/**") - .allowedOrigins("http://localhost:3000", "http://game-lounge.com") - .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") - .allowCredentials(true) - .allowedHeaders("*") - .exposedHeaders("Access-Control-Allow-Origin", "Cookie", "Set-Cookie") - } - } - } -} +class AnnotationServiceApplication fun main(args: Array) { runApplication(*args) diff --git a/app/annotation-service/src/main/kotlin/com/group6/annotationservice/controller/AnnotationController.kt b/app/annotation-service/src/main/kotlin/com/group6/annotationservice/controller/AnnotationController.kt index 42f9c2b2..8fcc8148 100644 --- a/app/annotation-service/src/main/kotlin/com/group6/annotationservice/controller/AnnotationController.kt +++ b/app/annotation-service/src/main/kotlin/com/group6/annotationservice/controller/AnnotationController.kt @@ -15,13 +15,11 @@ class AnnotationController( private val annotationService: AnnotationService ) { @PostMapping("parse-selector") - @CrossOrigin(origins = ["http://localhost:3000", "http://game-lounge.com"]) fun parseSelector(@RequestBody selector: SelectorDto): ResponseEntity { return ResponseEntity.ok("test") } @PostMapping("/create") - @CrossOrigin(origins = ["http://localhost:3000", "http://game-lounge.com"]) fun createAnnotation(@RequestBody annotationDto: AnnotationDto): ResponseEntity { val responseAnnotation = DtoConverter @@ -30,7 +28,6 @@ class AnnotationController( } @GetMapping("/{id}") - @CrossOrigin(origins = ["http://localhost:3000", "http://game-lounge.com"]) fun getAnnotation(@PathVariable id: String): ResponseEntity { val annotation = annotationService.getAnnotation(id) ?: return ResponseEntity(HttpStatus.NOT_FOUND) @@ -40,7 +37,6 @@ class AnnotationController( } @PostMapping("/get-annotations-by-target") - @CrossOrigin(origins = ["http://localhost:3000", "http://game-lounge.com"]) fun getAnnotationsByTarget(@RequestBody request: GetAnnotationsByTargetIdRequest): ResponseEntity> { val annotations = annotationService.getAnnotationsByTarget(request.targetId) val responseAnnotationList = annotations.map { DtoConverter.convertAnnotationToAnnotationDto(it) } @@ -48,7 +44,6 @@ class AnnotationController( } @DeleteMapping("/{id}") - @CrossOrigin(origins = ["http://localhost:3000", "http://game-lounge.com"]) fun deleteAnnotation(@PathVariable id: String): ResponseEntity { return if (annotationService.deleteAnnotation(id)) { ResponseEntity(HttpStatus.NO_CONTENT) @@ -56,4 +51,4 @@ class AnnotationController( ResponseEntity(HttpStatus.NOT_FOUND) } } -} +} \ No newline at end of file diff --git a/app/backend/README.md b/app/backend/README.md index 4f67095c..ebb969bb 100644 --- a/app/backend/README.md +++ b/app/backend/README.md @@ -53,3 +53,4 @@ docker run --detach -p 8080:8080 -e SPRING_DATASOURCE_URL="jdbc:postgresql:// invocation.arguments[0] as Game } - `when`(s3Service.uploadGamePictureAndReturnURL(any(MultipartFile::class.java), anyLong())).thenReturn("image-url.jpg") - // Act - val result = gameService.createGame(sessionId, createGameRequest, image) - - // Assert - assertEquals(createGameRequest.title, result.title) - assertEquals(createGameRequest.description, result.description) - assertEquals(createGameRequest.genres, result.genres) - assertEquals(createGameRequest.platforms, result.platforms) - assertEquals(createGameRequest.playerNumber, result.playerNumber) - assertEquals(createGameRequest.releaseYear, result.releaseYear) - assertEquals(createGameRequest.universe, result.universe) - assertEquals(createGameRequest.mechanics, result.mechanics) - assertEquals(createGameRequest.playtime, result.playtime) - assertEquals(createGameRequest.totalRating, result.totalRating) - assertEquals(createGameRequest.countRating, result.countRating) - assertEquals(createGameRequest.averageRating, result.averageRating) - } - - @Test - fun `createEditingRequest should create and return a new editing request`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val createEditingRequest = CreateEditingRequest( - title = "Updated Title", - description = "Updated Description", - genres = listOf("ACTION"), - platforms = listOf("PC"), - playerNumber = NumberOfPlayers.Single, - releaseYear = 2023, - universe = UniverseInfo.Historical, - mechanics = GameMechanics.TurnBased, - playtime = "15 hours", - totalRating = 0, - countRating = 0, - averageRating = 0.0 - ) - val editedImage: MultipartFile? = mock() val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED) - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(editedGameRepository.findByGameId(gameId)).thenReturn(emptyList()) - `when`(editedGameRepository.save(any(RequestedEditingGame::class.java))).thenAnswer { invocation -> invocation.arguments[0] as RequestedEditingGame } - `when`(s3Service.uploadEditedGamePictureAndReturnURL(any(MultipartFile::class.java), anyLong())).thenReturn("edited-image-url.jpg") + whenever(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) + whenever(userRepository.findById(userId)).thenReturn(Optional.of(user)) + whenever(gameRepository.save(any())).thenAnswer { invocation -> invocation.arguments[0] as Game } - // Act - gameService.createEditingRequest(sessionId, createEditingRequest, editedImage, gameId) + val result = gameService.createGame(sessionId, gameRequest, null) - // Assert - verify(editedGameRepository).save(any(RequestedEditingGame::class.java)) + assertNotNull(result) + assertEquals(gameRequest.title, result.title) + assertEquals(gameRequest.description, result.description) + assertEquals(gameRequest.genre, result.genre) + assertEquals(gameRequest.platform, result.platform) + assertEquals(gameRequest.playerNumber, result.playerNumber) + assertEquals(gameRequest.releaseYear, result.releaseYear) + assertEquals(gameRequest.universe, result.universe) + assertEquals(gameRequest.mechanics, result.mechanics) + assertEquals(gameRequest.playtime, result.playtime) + assertEquals(gameRequest.totalRating, result.totalRating) + assertEquals(gameRequest.countRating, result.countRating) + assertEquals(gameRequest.averageRating, result.averageRating) + assertEquals(user, result.user) } @Test - fun `deleteGame should mark the game as deleted`() { - // Arrange + fun `createGame should create and save game with image`() { val sessionId = UUID.randomUUID() val userId = 123L - val gameId = 1L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - - // Act - gameService.deleteGame(sessionId, gameId) - - // Assert - assertTrue(game.isDeleted) - } - - @Test - fun `getAllGames should return a list of approved and non-deleted games`() { - // Arrange - val games = listOf( - Game(title = "Game1", status = GameStatus.APPROVED), - Game(title = "Game2", status = GameStatus.PENDING_APPROVAL), - Game(title = "Game3", status = GameStatus.APPROVED, isDeleted = true), - Game(title = "Game4", status = GameStatus.APPROVED) + val gameRequest = CreateGameRequest( + title = "Game Title", + description = "Description", + genre = GameGenre.FIGHTING, + platform = GamePlatform.COMPUTER, + playerNumber = NumberOfPlayers.MULTIPLE, + releaseYear = 2020, + universe = UniverseInfo.FANTASY, + mechanics = GameMechanics.CHANCE_BASED, + playtime = "100", + totalRating = 0, + countRating = 0, + averageRating = 0.0, ) - `when`(gameRepository.findAll()).thenReturn(games) - - // Act - val result = gameService.getAllGames() - - // Assert - assertEquals(2, result.size) - assertEquals("Game1", result[0].title) - assertEquals("Game4", result[1].title) - // Add more assertions based on your requirements - } - - @Test - fun `rateGame should update the game's rating and return the modified game`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED, totalRating = 10, countRating = 2) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - `when`(userGameRatingRepository.findByUserAndGame(user, game)).thenReturn(emptyList()) - - // Act - val result = gameService.rateGame(sessionId, gameId, score) - - // Assert - assertEquals(score.toDouble(), result.averageRating) - assertEquals(12, result.totalRating) - assertEquals(3, result.countRating) - } - - @Test - fun `rateGame should update the user's rating for the game if already rated`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED, totalRating = 10, countRating = 2) - val userGameRating = UserGameRating(user = user, game = game, score = 3) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - `when`(userGameRatingRepository.findByUserAndGame(user, game)).thenReturn(listOf(userGameRating)) - - // Act - val result = gameService.rateGame(sessionId, gameId, score) - - // Assert - assertEquals(score.toDouble(), result.averageRating) - assertEquals(11, result.totalRating) - assertEquals(2, result.countRating) - } - - @Test - fun `rateGame should throw WrongRatingGameException for an invalid rating score`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val invalidScore = 6L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - - // Act and Assert - assertThrows { - gameService.rateGame(sessionId, gameId, invalidScore) - } - } - - @Test - fun `deleteGame should throw UnauthorizedGameAccessException if the user is not the owner`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val ownerUserId = 456L - val user = User(userId = userId) - val owner = User(userId = ownerUserId) - val game = Game(gameId = gameId, user = owner, status = GameStatus.APPROVED) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - - // Act and Assert - assertThrows { - gameService.deleteGame(sessionId, gameId) - } - } - - @Test - fun `deleteGame should throw DeletedGameException if the game is already deleted`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED, isDeleted = true) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - - // Act and Assert - assertThrows { - gameService.deleteGame(sessionId, gameId) - } - } - - @Test - fun `rateGame should update the rating of the game and create a UserGameRating`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED) - val userGameRating = UserGameRating(user = user, game = game, score = 0) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(userGameRatingRepository.findByUserAndGame(user, game)).thenReturn(emptyList()) - `when`(userGameRatingRepository.save(any(UserGameRating::class.java))).thenAnswer { invocation -> invocation.arguments[0] as UserGameRating } - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - - // Act - val result = gameService.rateGame(sessionId, gameId, score) - - // Assert - assertEquals(score, result.averageRating) - verify(userGameRatingRepository).save(any(UserGameRating::class.java)) - } - - @Test - fun `rateGame should update the rating of the game and update the UserGameRating`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED) - val existingUserGameRating = UserGameRating(user = user, game = game, score = 3) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(userGameRatingRepository.findByUserAndGame(user, game)).thenReturn(listOf(existingUserGameRating)) - `when`(userGameRatingRepository.save(any(UserGameRating::class.java))).thenAnswer { invocation -> invocation.arguments[0] as UserGameRating } - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - - // Act - val result = gameService.rateGame(sessionId, gameId, score) - - // Assert - assertEquals(score, result.averageRating) - verify(userGameRatingRepository).save(any(UserGameRating::class.java)) - // Add more assertions based on your requirements - } - - @Test - fun `rateGame should throw DeletedGameException if the game is already deleted`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED, isDeleted = true) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - - // Act and Assert - assertThrows { - gameService.rateGame(sessionId, gameId, score) - } - } - - @Test - fun `getGame should throw GameNotFoundException if the game does not exist`() { - // Arrange - val sessionId = UUID.randomUUID() - val gameId = 1L - - `when`(gameRepository.findById(gameId)).thenReturn(Optional.empty()) - - // Act and Assert - assertThrows { - gameService.getGame(gameId) - } - } - - @Test - fun `getEditingGame should throw GameNotFoundException if the editing game does not exist`() { - // Arrange - val sessionId = UUID.randomUUID() - val editingGameId = 1L + val image: MultipartFile = mock() - `when`(editedGameRepository.findByGameId(editingGameId)).thenReturn(emptyList()) - - // Act and Assert - assertThrows { - gameService.getEditingGame(editingGameId) + whenever(s3Service.uploadProfilePictureAndReturnURL(image, userId)).thenReturn("imageUrl") + whenever(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) + whenever(userRepository.findById(userId)).thenReturn(Optional.of(User(userId = userId))) + whenever(gameRepository.save(any())).thenAnswer { invocation -> + (invocation.arguments[0] as Game).apply { gamePicture = "imageUrl" } } - } - - @Test - fun `createGame should update game similarity`() { - // Arrange - val sessionId = UUID.randomUUID() - // Provide necessary details for creating a game - val createGameRequest = CreateGameRequest( - title = "New Game", - description = "Game description", - genres = listOf("ACTION", "ADVENTURE"), - platforms = listOf("PC", "XBOX"), - playerNumber = NumberOfPlayers.Multiplayer, - releaseYear = 2022, - universe = UniverseInfo.Fantasy, - mechanics = GameMechanics.RealTime, - playtime = "10 hours", - totalRating = 0, - countRating = 0, - averageRating = 0.0 - ) - val image: MultipartFile? = mock() - - val user = User(userId = 123L) - - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(user.userId) - `when`(userRepository.findById(user.userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - `when`(s3Service.uploadGamePictureAndReturnURL(any(MultipartFile::class.java), anyLong())).thenReturn("image-url.jpg") - // Act - gameService.createGame(sessionId, createGameRequest, image) + val result = gameService.createGame(sessionId, gameRequest, image) - // Assert - verify(gameSimilarityService).updateSimilarGamesField(any(Game::class.java)) - verify(gameRepository).save(any(Game::class.java)) + assertNotNull(result) + assertEquals("imageUrl", result.gamePicture) } - // Add other tests related to game similarity as needed - @Test - fun `rateGame should update the game's rating and game similarity`() { - // Arrange - val sessionId = UUID.randomUUID() - val userId = 123L - val gameId = 1L - val score = 4L - val user = User(userId = userId) - val game = Game(gameId = gameId, user = user, status = GameStatus.APPROVED, totalRating = 10, countRating = 2) - `when`(sessionAuth.getUserIdFromSession(sessionId)).thenReturn(userId) - `when`(userRepository.findById(userId)).thenReturn(Optional.of(user)) - `when`(gameRepository.findById(gameId)).thenReturn(Optional.of(game)) - `when`(gameRepository.save(any(Game::class.java))).thenAnswer { invocation -> invocation.arguments[0] as Game } - `when`(userGameRatingRepository.findByUserAndGame(user, game)).thenReturn(emptyList()) - // Act - val result = gameService.rateGame(sessionId, gameId, score) - - // Assert - assertEquals(score.toDouble(), result.averageRating) - assertEquals(12, result.totalRating) - assertEquals(3, result.countRating) - - verify(gameSimilarityService).updateSimilarGamesField(any(Game::class.java)) - verify(userGameRatingRepository).save(any(UserGameRating::class.java)) - } -} +} \ No newline at end of file diff --git a/app/backend/src/test/kotlin/com/gamelounge/backend/PostServiceTest.kt b/app/backend/src/test/kotlin/com/gamelounge/backend/PostServiceTest.kt index eebe1229..d192a413 100644 --- a/app/backend/src/test/kotlin/com/gamelounge/backend/PostServiceTest.kt +++ b/app/backend/src/test/kotlin/com/gamelounge/backend/PostServiceTest.kt @@ -24,18 +24,17 @@ class PostServiceTest { private val reportRepository: ReportRepository = mock() private val objectMapper: ObjectMapper = mock() private val tagService: TagService = mock() - private val recommendationService: RecommendationService = mock() + private val converterDto : ConverterDTO = mock() private val gameService: GameService = mock() private val postService = PostService( - postRepository, - sessionAuth, - userRepository, - reportRepository, - objectMapper, - tagService, - recommendationService, - gameService + postRepository, + sessionAuth, + userRepository, + reportRepository, + objectMapper, + tagService, + gameService ) @Test @@ -76,9 +75,7 @@ class PostServiceTest { assertEquals(user, result.user) assertTrue(result.postTags.containsAll(postTags)) } - - //problamatic for GameServiceTest - /*@Test + @Test fun `updatePost should update and return post when user is authorized`() { val sessionId = UUID.randomUUID() val postId = 1L @@ -113,10 +110,8 @@ class PostServiceTest { assertEquals(updatedPostRequest.content, result.content) assertEquals(updatedPostRequest.category, result.category) assertTrue(result.postTags.containsAll(updatedTags)) - }*/ + } - //problematic for GameServiceTest - /* @Test fun `updatePost should throw UnauthorizedPostAccessException when user is not authorized`() { val sessionId = UUID.randomUUID() @@ -133,10 +128,8 @@ class PostServiceTest { assertThrows { postService.updatePost(sessionId, postId, updatedPostRequest) } - }*/ + } - //problematic for GameServiceTest - /* @Test fun `deletePost should successfully delete post when user is authorized`() { val sessionId = UUID.randomUUID() @@ -155,7 +148,7 @@ class PostServiceTest { postService.deletePost(sessionId, postId) verify(postRepository).delete(post) - }*/ + } @Test fun `deletePost should throw UnauthorizedPostAccessException when user is not authorized`() { val sessionId = UUID.randomUUID() diff --git a/app/backend/src/test/kotlin/com/gamelounge/backend/UserServiceTest.kt b/app/backend/src/test/kotlin/com/gamelounge/backend/UserServiceTest.kt index 1999a2d4..06d6515f 100644 --- a/app/backend/src/test/kotlin/com/gamelounge/backend/UserServiceTest.kt +++ b/app/backend/src/test/kotlin/com/gamelounge/backend/UserServiceTest.kt @@ -5,7 +5,10 @@ import com.gamelounge.backend.entity.User import com.gamelounge.backend.exception.UsernameNotFoundException import com.gamelounge.backend.middleware.SessionAuth import com.gamelounge.backend.model.request.UpdateUserRequest -import com.gamelounge.backend.repository.* +import com.gamelounge.backend.repository.GameRepository +import com.gamelounge.backend.repository.PostRepository +import com.gamelounge.backend.repository.SessionRepository +import com.gamelounge.backend.repository.UserRepository import com.gamelounge.backend.service.AccessService import com.gamelounge.backend.service.S3Service import com.gamelounge.backend.service.TagService @@ -25,22 +28,20 @@ class UserServiceTest { private val userRepository: UserRepository = mock() private val postRepository: PostRepository = mock() private val gameRepository: GameRepository = mock() - private val sessionAuth: SessionAuth = mock() private val s3Service: S3Service = mock() private val tagService: TagService = mock() + private val sessionAuth: SessionAuth = mock() private val accessService: AccessService = mock() - private val reportRepository: ReportRepository = mock() private val userService = UserService( - sessionRepository, - userRepository, - postRepository, - gameRepository, - sessionAuth, - s3Service, - tagService, - accessService, - reportRepository + sessionRepository, + userRepository, + postRepository, + gameRepository, + sessionAuth, + s3Service, + tagService, + accessService ) @Test fun `updateUser should update all fields when provided`() { diff --git a/app/backend/test.txt b/app/backend/test.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/app/backend/test.txt @@ -0,0 +1 @@ + diff --git a/app/frontend/README.md b/app/frontend/README.md index 80737f14..3a8cced0 100644 --- a/app/frontend/README.md +++ b/app/frontend/README.md @@ -55,3 +55,4 @@ The command "docker run -p 3000:3000 -d game-lounge" starts a Docker container f Please note that one needs to setup a simple .env file before running it as the the backend url is defined by it. It's enough to define REACT_APP_API_URL (either localhost:8080 or some remote url). + diff --git a/app/frontend/src/App.js b/app/frontend/src/App.js index f3add35b..d48e4abf 100644 --- a/app/frontend/src/App.js +++ b/app/frontend/src/App.js @@ -8,16 +8,15 @@ import { ForumPage } from './pages/ForumPage' import { PostPage } from './pages/PostPage' import { NextUIProvider } from '@nextui-org/react' import { GameForum } from './pages/GameForum' -import { LfgPage } from './pages/LfgPage' -import Lfg from './pages/LfgPage/Lfg' +import { LfgPage } from "./pages/LfgPage"; +import Lfg from "./pages/LfgPage/Lfg"; import { AdminPanel } from './pages/AdminPanel' -import Search from './pages/Search/Search' + const App = () => ( } /> - } /> } /> } /> } /> @@ -37,3 +36,4 @@ const App = () => ( ) export default App + diff --git a/app/frontend/src/components/CommentCard.js b/app/frontend/src/components/CommentCard.js index 647eeb6c..9dba4318 100644 --- a/app/frontend/src/components/CommentCard.js +++ b/app/frontend/src/components/CommentCard.js @@ -1,16 +1,31 @@ import React from 'react' import userlogo from '../user.jpg' import ReportIcon from '@mui/icons-material/Report' +import DeleteIcon from '@mui/icons-material/Delete' +import { deleteComment } from '../services/commentService' const CommentCard = ({ comment, onUpvote, onDownvote, currentUser }) => { const isCurrentUserCreator = comment.creatorUser.username === currentUser.username + const handleDeleteComment = async (commentId) => { + try { + await deleteComment(commentId) + window.location.reload() + } catch (error) { + console.error('Error deleting post:', error) + } + } + return ( -
+

{comment.content}

- {isCurrentUserCreator ? null : ( + {isCurrentUserCreator ? ( + + ) : ( diff --git a/app/frontend/src/components/PostCard.js b/app/frontend/src/components/PostCard.js index c10e9609..97070faa 100644 --- a/app/frontend/src/components/PostCard.js +++ b/app/frontend/src/components/PostCard.js @@ -4,6 +4,7 @@ import EditPost from '../pages/ForumPage/EditPost' import { deletePost } from '../services/postService' import { useNavigate } from 'react-router-dom' import { useParams } from 'react-router-dom' +import DeleteIcon from '@mui/icons-material/Delete' const PostCard = ({ post, currentUser, onUpvote, onDownvote }) => { const isCurrentUserCreator = currentUser && post.creatorUser.username === currentUser.username ? true : false @@ -31,7 +32,7 @@ const PostCard = ({ post, currentUser, onUpvote, onDownvote }) => { className='btn btn-sm bg-neutral-200 border-none hover:bg-neutral-300' title='Delete Post' > - 🗑️ + )} diff --git a/app/frontend/src/components/navbar/Navbar.js b/app/frontend/src/components/navbar/Navbar.js index 3e6c2817..04148d4f 100644 --- a/app/frontend/src/components/navbar/Navbar.js +++ b/app/frontend/src/components/navbar/Navbar.js @@ -19,7 +19,6 @@ import { useState, useEffect } from 'react' import axios from 'axios' import { useNavigate } from 'react-router-dom' import logo from '../../gamelounge.png' -import { getAllSearch } from '../../services/searchService.js' import {getUserInfoBySessionId} from "../../services/userService"; const Navbarx = () => { const api_url = process.env.REACT_APP_API_URL @@ -98,31 +97,7 @@ const Navbarx = () => { if (isAdmin) { setIsAdmin(true) } - }, []) - const [searchResults, setSearchResults] = useState([]) - const [searchQuery, setSearchQuery] = useState('') - const navigateToSearch = (result) => { - // Use the 'navigate' function from 'react-router-dom' to navigate to the Search component - navigate('/search', { state: { searchData: result } }) - } - const handleSearch = async () => { - try { - const response = await getAllSearch(searchQuery) - - if (response.status === 200) { - setSearchResults(response.data) - console.log(searchResults) - navigateToSearch(response.data) - } - } catch (error) { - console.error(error) - } - } - - const handleInputChange = (e) => { - setSearchQuery(e.target.value) - // Trigger search when the user stops typing for 300 milliseconds - } + }, []) useEffect(() => { const fetchUserInfo = async () => { @@ -186,12 +161,6 @@ const Navbarx = () => { size='sm' startContent={} type='search' - onChange={handleInputChange} - onKeyDown={(e) => { - if (e.key === 'Enter') { - handleSearch() - } - }} /> {isLoggedIn ? ( @@ -225,11 +194,6 @@ const Navbarx = () => { size='sm' startContent={} type='search' - onKeyDown={(e) => { - if (e.key === 'Enter') { - handleSearch() - } - }} /> ) : null} diff --git a/app/frontend/src/pages/ForumPage/SelectTags.js b/app/frontend/src/pages/ForumPage/SelectTags.js index 3a53321f..dcb666a7 100644 --- a/app/frontend/src/pages/ForumPage/SelectTags.js +++ b/app/frontend/src/pages/ForumPage/SelectTags.js @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React, { useState } from 'react'; import Box from '@mui/material/Box'; import FormLabel from '@mui/material/FormLabel'; import FormControl from '@mui/material/FormControl'; @@ -8,6 +8,9 @@ import Checkbox from '@mui/material/Checkbox'; import { grey } from '@mui/material/colors'; const TagSelection = ({ tags, selectedTags, handleTagChange }) => { + const [showMore, setShowMore] = useState(false); + const maxTagsToShow = 5; + const handleCheckboxChange = (event, tag) => { const updatedTags = event.target.checked ? [...selectedTags, tag] @@ -16,7 +19,9 @@ const TagSelection = ({ tags, selectedTags, handleTagChange }) => { handleTagChange(updatedTags); }; - const tagCheckboxes = tags.map((tag) => ( + const visibleTags = showMore ? tags : tags.slice(0, maxTagsToShow); + + const tagCheckboxes = visibleTags.map((tag) => ( { /> )); + const showMoreButton = tags.length > maxTagsToShow && ( + + ); + return ( @@ -39,6 +50,7 @@ const TagSelection = ({ tags, selectedTags, handleTagChange }) => { {tagCheckboxes} + {showMoreButton} ); diff --git a/app/frontend/src/pages/HomePage/Group.js b/app/frontend/src/pages/HomePage/Group.js index f2d27b52..7a10f3c0 100644 --- a/app/frontend/src/pages/HomePage/Group.js +++ b/app/frontend/src/pages/HomePage/Group.js @@ -1,28 +1,30 @@ -import React from 'react' -import {Link} from "react-router-dom"; +import React from 'react'; +import { Link } from 'react-router-dom'; +import profileIcon from "./profile.jpg"; -const Group = ({ item }) => { - return ( -
-
- Group -
-
-

{item.title}

-

{item.text}

-
- - Players: {item.totalMembers}/{item.memberCapacity} - - -
-
-
- ) -} +const Group = ({ group }) => { + return ( +
+
+ Post { + e.target.src = profileIcon; + }}/> +
+
+

+ + {group.title} + +

+

Game: {group.relatedGame}

+

Language: {group.requiredLanguage}

+

Platform: {group.requiredPlatform}

+
+ +
+
+
+ ); + } -export default Group + export default Group; diff --git a/app/frontend/src/pages/HomePage/HomePage.js b/app/frontend/src/pages/HomePage/HomePage.js index 7fe8e8d5..2fb58d2c 100644 --- a/app/frontend/src/pages/HomePage/HomePage.js +++ b/app/frontend/src/pages/HomePage/HomePage.js @@ -14,9 +14,10 @@ import alikasap from './alikasap.jpg' import { getRecommendedGroups, getAllGroups } from '../../services/lfgService' export default function HomePage() { - const [gamesData, setGamesData] = useState([]) - const [postData, setPostData] = useState([]) - const [groupData, setGroupData] = useState([]) + const [gamesData, setGamesData] = useState([]); + const [postData, setPostData] = useState([]); + const [groupData, setGroupData] = useState([]); + useEffect(() => { const fetchGames = async () => { try { @@ -85,30 +86,6 @@ export default function HomePage() { } ] - // const postData = [ - // { - // image: `https://primefaces.org/cdn/primereact/images/product/game-controller.jpg}`, - // header: 'Resident Evil 4 Remake', - // content: - // "Looking for someone to join me in my Resident Evil 4 adventure! Let's team up and face the horrors together.️ #ResidentEvil4 #GamingBuddyWanted", - // date: '29.10.2023 00.00' - // }, - // { - // image: 'https://primefaces.org/cdn/primereact/images/product/game-controller.jpg', - // header: 'Fifa', - // content: - // 'FIFA is one of the most popular football simulation games developed by EA Sports. It offers an immersive gaming experience with realistic graphics, player mechanics, and stadiums.', - // date: '29.10.2023 00.00' - // }, - // { - // image: `https://primefaces.org/cdn/primereact/images/product/game-controller.jpg}`, - // header: 'The Witcher 3: Wild Hunt', - // content: - // "The Witcher 3 is an unforgettable gaming experience. Its open world, rich storytelling, and captivating characters make it a must-play RPG. If you love epic adventures, this one's a masterpiece.", - // date: '29.10.2023 00.00' - // } - // ] - console.log(postData) return ( diff --git a/app/frontend/src/pages/HomePage/Post.js b/app/frontend/src/pages/HomePage/Post.js index 14122bc0..f0b017be 100644 --- a/app/frontend/src/pages/HomePage/Post.js +++ b/app/frontend/src/pages/HomePage/Post.js @@ -1,11 +1,14 @@ import React from 'react'; import { Link } from 'react-router-dom'; +import profileIcon from "./profile.jpg"; const Post = ({ post }) => { return (
- Post + Post { + e.target.src = profileIcon; + }}/>

diff --git a/app/frontend/src/pages/HomePage/profile.jpg b/app/frontend/src/pages/HomePage/profile.jpg new file mode 100644 index 00000000..245d9bfe Binary files /dev/null and b/app/frontend/src/pages/HomePage/profile.jpg differ diff --git a/app/frontend/src/pages/LfgPage/EditLfg.js b/app/frontend/src/pages/LfgPage/EditLfg.js index 8432da7b..2ba8692b 100644 --- a/app/frontend/src/pages/LfgPage/EditLfg.js +++ b/app/frontend/src/pages/LfgPage/EditLfg.js @@ -130,7 +130,7 @@ export default function EditLfg(props) { - Edit Lfg + Create Lfg diff --git a/app/frontend/src/pages/LfgPage/Lfg.js b/app/frontend/src/pages/LfgPage/Lfg.js index 7009c044..9ee4af8f 100644 --- a/app/frontend/src/pages/LfgPage/Lfg.js +++ b/app/frontend/src/pages/LfgPage/Lfg.js @@ -80,33 +80,6 @@ const Lfg = () => { } }; - const [isMember, setIsMember] = React.useState(true); - - const isUserGroupMember = async (user, group) => { - try { - const userId = user?.userId; - const members = group?.members; - - if (!userId || !members) { - return false; - } - - const isMember = members.some(member => member.userId === userId); - return isMember; - } catch (error) { - return false; - } - }; - - useEffect(() => { - const fetchIsMember = async () => { - const result = await isUserGroupMember(currentUser, lfg); - setIsMember(result); - }; - - fetchIsMember(); - }, [currentUser, lfg]); - return ( <> @@ -126,21 +99,18 @@ const Lfg = () => { /> ))}

- {isMember && } - {isMember && + >
- }
diff --git a/app/frontend/src/pages/LfgPage/LfgCard.js b/app/frontend/src/pages/LfgPage/LfgCard.js index e96dd823..3495aec6 100644 --- a/app/frontend/src/pages/LfgPage/LfgCard.js +++ b/app/frontend/src/pages/LfgPage/LfgCard.js @@ -150,16 +150,14 @@ const LfgCard = ({ group, currentUser }) => {

{group.description}

-
-
-

Platform: {group.requiredPlatform}

-
+
+

Game: {group.relatedGame}

Language: {group.requiredLanguage}

+

Platform: {group.requiredPlatform}

Mic/Cam: {group.micCamRequirement ? "yes" : "no"}

- {false &&

Game: {group.relatedGame}

}
diff --git a/app/frontend/src/pages/LfgPage/LfgPage.js b/app/frontend/src/pages/LfgPage/LfgPage.js index 4cecaf91..7d6cb365 100644 --- a/app/frontend/src/pages/LfgPage/LfgPage.js +++ b/app/frontend/src/pages/LfgPage/LfgPage.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import Navbarx from '../../components/navbar/Navbar'; +// import { getAllPosts } from '../../services/postService'; import LfgCard from "./LfgCard"; import {getUserInfoBySessionId} from "../../services/userService"; import {getAllGroups} from "../../services/lfgService"; @@ -9,6 +10,7 @@ export default function LfgPage() { const [groups, setGroups] = useState([]); const [isLoading, setIsLoading] = useState(true); +// const [filteredPosts, setFilteredPosts] = useState([]); const [currentUser, setCurrentUser] = useState(null); diff --git a/app/frontend/src/pages/PostPage/PostPage.js b/app/frontend/src/pages/PostPage/PostPage.js index cbafa544..f4230cad 100644 --- a/app/frontend/src/pages/PostPage/PostPage.js +++ b/app/frontend/src/pages/PostPage/PostPage.js @@ -118,8 +118,9 @@ const PostPage = () => { /> ))}
-