Changeset 890e036


Ignore:
Timestamp:
02/09/26 21:45:41 (5 months ago)
Author:
Filip Gavrilovski <filipgavrilovski28@…>
Branches:
main
Children:
0808ef2
Parents:
03a8d87 (diff), 27660af (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'main' into gavro/features

Files:
5 added
13 edited

Legend:

Unmodified
Added
Removed
  • finkwave/.gitignore

    r03a8d87 r890e036  
    3232### VS Code ###
    3333.vscode/
    34 application.properties
     34application*.properties
    3535
    3636uploads/profile-pictures/*
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/SongController.java

    r03a8d87 r890e036  
    11package com.ukim.finki.develop.finkwave.controller;
    22
    3 import com.ukim.finki.develop.finkwave.model.dto.BasicSongDto;
    4 import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
    5 import com.ukim.finki.develop.finkwave.model.dto.SongDetailsDto;
    6 import com.ukim.finki.develop.finkwave.model.dto.SongDto;
     3import com.ukim.finki.develop.finkwave.model.dto.*;
    74import com.ukim.finki.develop.finkwave.repository.SongRepository;
    85import com.ukim.finki.develop.finkwave.service.AuthService;
     
    4239        return ResponseEntity.ok(songService.getSongDetails(songId));
    4340    }
     41
     42    @GetMapping("/catalog")
     43    public HttpEntity<List<MusicalEntitesByArtistDto>> getArtistCatalog(){
     44        List<MusicalEntitesByArtistDto> artistCatalog = songService.getArtistCatalog();
     45        return ResponseEntity.ok(artistCatalog);
     46    }
    4447}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/TestController.java

    r03a8d87 r890e036  
    11package com.ukim.finki.develop.finkwave.controller;
    22
    3 import com.ukim.finki.develop.finkwave.model.MusicalEntity;
    4 import com.ukim.finki.develop.finkwave.model.User;
    5 import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
    63import com.ukim.finki.develop.finkwave.model.dto.SongDto;
     4import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
    75import com.ukim.finki.develop.finkwave.repository.SongRepository;
    86import com.ukim.finki.develop.finkwave.repository.UserRepository;
    97import lombok.AllArgsConstructor;
    10 import lombok.Getter;
    118import org.springframework.http.HttpEntity;
    129import org.springframework.http.ResponseEntity;
     
    2825
    2926    @GetMapping("/search/u/{searchTerm}")
    30     public HttpEntity<List<User>> searchUsersTest(@PathVariable String searchTerm){
    31         return ResponseEntity.ok(userRepository.searchListeners(searchTerm));
     27    public HttpEntity<List<UserSearchResultDto>> searchUsersTest(@PathVariable String searchTerm){
     28        return ResponseEntity.ok(userRepository.searchListeners(searchTerm, 10));
    3229    }
    3330    @GetMapping("/search/a/{searchTerm}")
    34     public HttpEntity<List<User>> searchArtistsTest(@PathVariable String searchTerm){
    35         return ResponseEntity.ok(userRepository.searchArtists(searchTerm));
     31    public HttpEntity<List<UserSearchResultDto>> searchArtistsTest(@PathVariable String searchTerm){
     32        return ResponseEntity.ok(userRepository.searchArtists(searchTerm, 10));
    3633    }
    3734}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UserController.java

    r03a8d87 r890e036  
    22
    33import com.ukim.finki.develop.finkwave.model.User;
     4import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
    45import com.ukim.finki.develop.finkwave.model.enums.UserType;
    56import com.ukim.finki.develop.finkwave.service.UserService;
     
    2425
    2526    @GetMapping("/search")
    26     public HttpEntity<List<User>> searchArtists(
     27    public HttpEntity<List<UserSearchResultDto>> searchArtists(
    2728            @RequestParam(name = "type") UserType userType,
    28             @RequestParam(name = "q") String searchTerm){
    29         return ResponseEntity.ok(usersService.search(userType, searchTerm));
     29            @RequestParam(name = "q") String searchTerm,
     30            @RequestParam(name = "limit", defaultValue = "10") Integer limit)
     31            {
     32        return ResponseEntity.ok(usersService.search(userType, searchTerm, limit));
    3033    }
    3134}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/UserResponseDto.java

    r03a8d87 r890e036  
    11package com.ukim.finki.develop.finkwave.model.dto;
    22
    3 import com.ukim.finki.develop.finkwave.model.Role;
    43import jakarta.annotation.Nullable;
    54import lombok.Builder;
     
    109        String username,
    1110        @Nullable String profilePhoto,
    12         Role role){
    13 }
     11        Boolean isAdmin,
     12        @Nullable Boolean isArtist
     13){}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SongRepository.java

    r03a8d87 r890e036  
    11package com.ukim.finki.develop.finkwave.repository;
    22
    3 import com.ukim.finki.develop.finkwave.model.dto.BasicSongDto;
    4 import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
    5 import com.ukim.finki.develop.finkwave.model.dto.SongDto;
     3import java.util.List;
     4
    65import org.springframework.data.jpa.repository.JpaRepository;
    76import org.springframework.data.jpa.repository.Query;
     
    109
    1110import com.ukim.finki.develop.finkwave.model.Song;
    12 
    13 import java.util.List;
     11import com.ukim.finki.develop.finkwave.model.dto.BasicSongDto;
     12import com.ukim.finki.develop.finkwave.model.dto.MusicalEntitesByArtistDto;
     13import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
     14import com.ukim.finki.develop.finkwave.model.dto.SongDto;
    1415
    1516@Repository
     
    119120                     JOIN songs s on s.id = l.song_id
    120121                     JOIN users u ON u.user_id = me.released_by
    121                      WHERE l.listener_id = 2
     122                     WHERE l.listener_id = :userId
    122123                 ORDER BY l.song_id, l.timestamp DESC
    123124             ) t
     
    155156    """)
    156157    SongDto getSongById(@Param("songId") Long songId, @Param("userId") Long userId);
     158
     159    @Query("""
     160        SELECT new com.ukim.finki.develop.finkwave.model.dto.MusicalEntitesByArtistDto(
     161          me.id,
     162          me.title,
     163          me.genre,
     164          (CASE WHEN EXISTS (SELECT 1 from Song s where me.id = s.id and s.album is null) THEN 'SONG' ELSE 'ALBUM' END),
     165          me.cover,
     166          me.releaseDate
     167        )
     168        FROM MusicalEntity me
     169        WHERE me.releasedBy.id = :artistId
     170        ORDER BY me.releaseDate DESC
     171    """)
     172    List<MusicalEntitesByArtistDto> getMusicalEntitiesReleasedByArtist(@Param("artistId")Long artistId);
    157173}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UserRepository.java

    r03a8d87 r890e036  
    22
    33import com.ukim.finki.develop.finkwave.model.User;
     4import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
    45import org.springframework.data.jpa.repository.JpaRepository;
    56import org.springframework.data.jpa.repository.Query;
     7import org.springframework.data.repository.query.Param;
    68import org.springframework.stereotype.Repository;
    79
     
    1416
    1517
    16     @Query("""
    17         SELECT u from User u
    18         WHERE (u.fullName ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%')
     18    @Query(value = """
     19        SELECT u.full_name, u.username, u.profile_photo from users u
     20        WHERE (u.full_name ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%')
    1921            and u.listener = true and u.artist = false
    20         """)
    21     List<User> searchListeners(String searchTerm);
     22        LIMIT :limit
     23        """, nativeQuery = true)
     24    List<UserSearchResultDto> searchListeners(@Param("searchTerm") String searchTerm, @Param("limit") Integer limit);
    2225
    23     @Query("""
    24         SELECT u from User u
    25         WHERE (u.fullName ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%')
    26             and u.artist = true
    27         """)
    28     List<User> searchArtists(String searchTerm);
     26    @Query(value = """
     27        SELECT u.full_name, u.username, u.profile_photo from users u
     28        WHERE (u.full_name ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%') and u.artist = true
     29        LIMIT :limit
     30        """, nativeQuery = true)
     31    List<UserSearchResultDto> searchArtists(@Param("searchTerm") String searchTerm, @Param("limit") Integer limit);
     32
     33
    2934}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java

    r03a8d87 r890e036  
    209209                .username(user.getUsername())
    210210                .profilePhoto(user.getProfilePhoto())
    211                 .role(user.getRole())
     211                .isAdmin(user.getRole().equals(Role.ADMIN))
     212                .isArtist(user.isArtist())
    212213                .build();
    213214    }
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/SongService.java

    r03a8d87 r890e036  
    5454        return songDetailsMapper.toSongDetailsDto(songDto, contributionsBySongId, reviewsForSongId);
    5555    }
     56
     57    public List<MusicalEntitesByArtistDto> getArtistCatalog(){
     58        Long userId = authService.getCurrentUserID();
     59        return songRepository.getMusicalEntitiesReleasedByArtist(userId);
     60    }
    5661}
  • finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UserService.java

    r03a8d87 r890e036  
    22
    33import com.ukim.finki.develop.finkwave.model.User;
     4import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
    45import com.ukim.finki.develop.finkwave.model.enums.UserType;
    56import com.ukim.finki.develop.finkwave.repository.UserRepository;
     
    1819    }
    1920
    20     // todo: add dto-s
    21 
    22     public List<User> search(UserType userType, String searchTerm){
    23 
     21    public List<UserSearchResultDto> search(UserType userType, String searchTerm, int limit){
    2422        return switch (userType) {
    25             case ARTIST -> usersRepository.searchArtists(searchTerm);
    26             case LISTENER -> usersRepository.searchListeners(searchTerm);
     23            case ARTIST -> usersRepository.searchArtists(searchTerm, limit);
     24            case LISTENER -> usersRepository.searchListeners(searchTerm, limit);
    2725            case null -> throw new IllegalArgumentException("Invalid userType");
    2826        };
  • frontend/src/App.tsx

    r03a8d87 r890e036  
    1717import Login from "./pages/Login";
    1818import MusicalCollection from "./pages/MusicalCollection";
     19import MySongs from "./pages/MySongs";
    1920import Nav from "./pages/Nav";
     21import PublishSong from "./pages/PublishSong";
    2022import Register from "./pages/Register";
    2123import SongDetail from "./pages/SongDetail";
     
    2830        // show sidebar only if user is logged in and is on the landing page
    2931        const isLandingPage = location.pathname === "/";
    30         const [isSidebarOpen, setIsSidebarOpen] = useState(!!user && isLandingPage);
     32        const [isSidebarOpen, setIsSidebarOpen] = useState(
     33                !!user && isLandingPage && !user?.isArtist && !user?.isAdmin,
     34        );
    3135
    3236        // Open sidebar when user logs in and navigates to landing page
    3337        useEffect(() => {
    34                 if (user && isLandingPage) {
     38                if (user && isLandingPage && !user.isArtist && !user.isAdmin) {
    3539                        setIsSidebarOpen(true);
    3640                }
     
    104108                        },
    105109                        {
     110                                path: "/my-songs",
     111                                element: <MySongs />,
     112                        },
     113                        {
     114                                path: "/publish",
     115                                element: <PublishSong />,
     116                        },
     117                        {
    106118                                path: "/songs/:id",
    107119                                element: <SongDetail />,
  • frontend/src/pages/Nav.tsx

    r03a8d87 r890e036  
    2222                        setUser(undefined);
    2323                        setIsDropdownOpen(false);
    24                         toast.success("Logout successful!");
     24                        window.location.href = "/";
     25                        // toast.success("Logout successful!");
    2526                } catch (error) {
    2627                        console.error("Logout failed:", error);
     
    8182                                {!isAuthLoading && (
    8283                                        <div className="flex items-center space-x-3">
     84                                                {user?.isArtist && (
     85                                                        <Link
     86                                                                to="/my-songs"
     87                                                                className="text-white hover:text-[#1db954] px-4 py-2 text-sm font-medium transition-colors"
     88                                                        >
     89                                                                My Songs
     90                                                        </Link>
     91                                                )}
    8392                                                {user ? (
    8493                                                        <div className="relative" ref={dropdownRef}>
  • frontend/src/utils/types.ts

    r03a8d87 r890e036  
    44        email?: string;
    55        profilePhoto?: string | null;
    6         role?: "ADMIN" | "NONADMIN";
     6        isAdmin: boolean;
     7        isArtist: boolean;
    78}
    89
     
    107108        songCount: number;
    108109}
     110
     111export interface CatalogItem {
     112        id: number;
     113        title: string;
     114        genre: string;
     115        cover: string | null;
     116        type: "SONG" | "ALBUM";
     117        releaseDate: string;
     118}
     119
     120export interface Contributor {
     121        username: string;
     122        fullName: string;
     123        role: string;
     124}
     125
     126export interface ArtistSearchResult {
     127        username: string;
     128        fullName: string;
     129        profilePhoto?: string;
     130}
     131
     132export interface SongEntry {
     133        title: string;
     134        link: string;
     135        contributors: Contributor[];
     136}
Note: See TracChangeset for help on using the changeset viewer.