Giter Site home page Giter Site logo

be-musicstreaming's Introduction

๐ŸŽธ Y2PLAY ๐ŸŽธ Backend

image

Topics


What is Y2PLAY ?

Y2Play - your one-stop shop, ultimate genie for playlist organization.

Who is the user ?

Y2Play is made by and for the music enthusiasts who wish to curate the vibes and manage their playlists, all at the same time.

MVP Features

  • Authenticate utilizing custom backend API calls and FireBase, OAuth authentication.
  • Create playlists.
  • Choose from a list of songs to add to playlists, features a many-to-many relationship between playlists and songs entity.
  • Have a playlist you're aboslutely obsessed with? Show it by favoriting it!
  • Filter playlists.
  • Edit playlist information such as name, image, or whether or not it is public.
  • Delete playlists.

Stretch Features

  • The ability to make playlists public - for others to view and pull inspo from.
  • A search function to allow for you to search for songs by song name, artist name, or genre name.
  • A discover function which allows you to view all public playlists created by users just like you!

Planning for Y2PLAY

Contributors

๐ŸŽง FRONTEND DEVS ๐ŸŽง

๐Ÿ’ฟ BACKEND DEVS ๐Ÿ’ฟ

be-musicstreaming's People

Contributors

dylankmoore avatar keanacobarde avatar cnfairall avatar

Watchers

 avatar

be-musicstreaming's Issues

GET all playlists

User Story

As a user, I want to be able to view all playlists so I can explore various music collections.

Acceptance Criteria

  • WHEN I navigate to the discover playlist / my playlists section in the app
  • THEN I should see a list of all available public playlists, & my own if I am logged in.

Dependencies

  • Requires authentication to be set up to identify my playlists.
  • #3 #4

Dev Notes

  • Implement a GET endpoint in the backend to retrieve all playlists.
  • The endpoint should differentiate between public playlists and user-specific playlists if the user is authenticated.

Example BE code:

app.MapGet("/playlists", (BE_MusicSharingDbContext db, User user) =>
{
    // retrieve all playlists, including public playlists & playlists belonging to the user
    var playlists = db.Playlists
        .Include(p => p.SongPlaylists).ThenInclude(sp => sp.Song).ThenInclude(s => s.Artist)
        .Where(p => p.Public || p.UserId == user.Id);

    // select relevant playlist details
    var playlistData = playlists.Select(p => new
    {
        p.PlaylistId,
        p.Name,
        p.DateCreated,
        p.Public,
        UserName = p.User.Username,
        Songs = p.SongPlaylists.Select(sp => new 
        {
            sp.Song.SongId,
            sp.Song.Name,
            ArtistName = sp.Song.Artist.Name
        })
    }).ToList();

    return Results.Ok(playlistData);
});

Example FE code:

// GET all playlists
const getPlaylists = () => {
  const url = `${endpoint}/playlists`;

  return new Promise((resolve, reject) => {
    fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    })
    .then(response => {
      if (!response.ok) {
        throw new Error('Failed to fetch playlists');
      }
      return response.json();
    })
    .then(data => resolve(data))
    .catch(error => reject(error));
  });
};

Filter songs by artist

User Story

As a user I want to see all the songs available from my favorite artist.

Acceptance Criteria

  • When on the songs page,
  • I should be able to select an artist from a dropdown menu
  • and then I should see the page populated only with songs by that artist

Dependencies

  • db creation

Dev Notes

  • make GET call to api/songs/artistId passing id as parameter
  • make list of songs where artist id == id
  • if not null, return list

DELETE a playlist

User Story

As a user, I want to be able to delete playlists that I no longer need, so that I can keep my playlist collection organized and clutter-free.

Acceptance Criteria

  • WHEN I navigate to the playlist detail page and select the option to delete a playlist
  • THEN I should receive a confirmation prompt asking me to confirm the deletion
  • AND upon confirming, the system should delete the playlist from my collection
  • AND I should receive a confirmation message indicating that the playlist has been successfully deleted

Dependencies

  • User authentication must be fully operational
  • The database must be configured to accept and store playlist data.
  • The frontend must provide a seamless option for deleting playlists.
  • #3 #4

Dev Notes

  • Implement a DELETE endpoint at /playlists/{playlistId} to handle the deletion of playlists.
  • The DELETE endpoint should remove the playlist from the database based on the provided playlist ID.

Ex. BE code(will prob need to be reworked w/ join table):

app.MapDelete("/playlists/{playlistId}", (BE-MusicStreamingDbContext db, int playlistId) =>
{
    var playlist = db.Playlists.FirstOrDefault(p => p.PlaylistId == playlistId);

    if (playlist == null)
    {
        return Results.NotFound("Playlist not found.");
    }

    db.Playlists.Remove(playlist);
    db.SaveChanges();

    return Results.Ok($"Playlist {playlistId} has been deleted.");
});

Ex. FE code:

const deletePlaylist = (playlistId) => {
  const url = `${endpoint}/playlists/${playlistId}`;

  return new Promise((resolve, reject) => {
    fetch(url, {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
      },
    })
    .then((response) => {
      if (!response.ok) {
        throw new Error('Failed to delete playlist');
      }
      return response.text();
    })
    .then((data) => resolve(data))
    .catch((error) => reject(error));
  });
};

GET - User by ID

User Story

  • I, as a user, should have access to my profile. This profile should show the details associated with my user, as outlined by the user entity.

Acceptance Criteria

  • Endpoint URL: "/user/{id}"
  • As highlighted by the ticket descriptions:
    Get User by ID: You should be able to view details associated with a profile.

Dependencies

  • This issue is dependent on the seeding of data

Dev Notes

GET - BY USER ID, RARE - W/O ENTITY FRAMEWORK

app.MapGet("/users/{id}", (int id) => {
    Users user = users.FirstOrDefault(u => u.Id == id);
    if (user == null)
    {
        return Results.NotFound();
    }
    return Results.Ok(user);
});

UPDATE a playlist

User Story

As a user, I want to be able to update the playlists I have created, changing details like the name, visibility, and favorite status, so that I can refine how I organize and share my music over time.

Acceptance Criteria

  • WHEN I click on "update" on one of my playlists,
  • THEN I should be able to modify its name, public/private status, and favorite status.
  • AND upon submitting these changes, the system should update the playlist with the new details.
  • AND I should likely receive a confirmation that the playlist has been updated.

Dependencies

  • User authentication must be fully operational to ensure only the playlist owner can update it.
  • The database must have existing playlists that can be updated.
  • The frontend must provide an interface for users to submit their updates.
  • #3 #4

Dev Notes

  • Implement a PUT endpoint at /playlists/{playlistId} to handle the updates of playlists.
  • The API should return 200 OK on successful update and 404 Not Found if the specified playlist does not exist.
  • Will likely need a DTO

Ex. of BE code (will need to probably be reworked with the join table):


    app.MapPut("/playlists/{playlistId}", (BE-MusicStreamingDbContext db, int playlistId, PlaylistUpdateDto playlistDto) =>
    {
        var playlist = db.Playlists.FirstOrDefault(p => p.PlaylistId == playlistId);

        if (playlist == null)
        {
            return Results.NotFound("Playlist not found.");
        }

        playlist.Name = playlistDto.Name ?? playlist.Name;
        playlist.Public = playlistDto.Public;
        playlist.IsFavorite = playlistDto.IsFavorite;

        db.SaveChanges();

        return Results.Ok(new
        {
            PlaylistId = playlist.PlaylistId,
            PlaylistName = playlist.Name,
            IsPublic = playlist.Public,
            IsFavorite = playlist.IsFavorite
        });
    });
}

Ex. of FE code:

const updatePlaylist = async (playlistId, updateData) => {
    const url = `${endpoint}/playlists/${playlistId}`;

    try {
        const response = await fetch(url, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(updateData)
        });

        if (!response.ok) {
            const message = await response.text();
            throw new Error(`Failed to update playlist`);
        }

        return await response.json(); 
    } catch (error) {
        console.error('Error updating playlist:', error);
        throw error;
    }
};

Get Single Song

User Story

As a user I need to select individual songs to add to my playlist.

Acceptance Criteria

  • When I view a song,
  • I should see its name, artist, year, genre, and duration
  • Then when I click the add to playlist button,
  • That song should be added to the playlist I select

Dependencies

  • db creation

Dev Notes

  • make GET call to api/songs/songid passing id as parameter
  • find song where its id === id
  • if not null, return song

Artist - GET + GET ARTIST BY ID

User Story

  • I, as the user, will need to get all artists as well as get an artist by ID, this allows me to see all the songs associated with an artist as well.

Acceptance Criteria

  • Endpoint Description: "/artist/{id}"
  • The user must be able to complete the following:

When navigating to the 'artists' page (if frontend is designing one), all artists along with their name should be present.
STRETCH: When selecting on an ArtistCard on the artists page, a user should be able to see all associated artist details.

Dependencies

  • Dependent on the seeding of test data.

Dev Notes

All setup issues need to be completed before this endpoint is built. Test data will need to be seeded, and class structure needs to exist.

Dev Notes

Typical 'GET' endpoints appear as follows:
NOTE: .Include() will need to be added to take into account items.
GET - CREEKRIVER

app.MapGet("/api/campsites", (CreekRiverDbContext db) =>
{
    return db.Campsites.ToList();
});

GET - BY USER ID, RARE - W/O ENTITY FRAMEWORK

app.MapGet("/users/{id}", (int id) => {
    Users user = users.FirstOrDefault(u => u.Id == id);
    if (user == null)
    {
        return Results.NotFound();
    }
    return Results.Ok(user);
});

Search songs by name, artist or genre

User Story

As a user I want to be able to search directly for a song instead of browsing

Acceptance Criteria

  • When I'm looking at the page
  • I should see a search bar
  • When I enter my search info
  • I should see a page with songs that meet my search criteria

Dependencies

db

Dev Notes

  • make GET call to api/songs passing searchInput string
  • make list of songs where artist name (song.artist.name) OR song.name OR song.genre.name contains string
  • if not null, return list

SETUP - ERD + EF and PostgreSQL Setup

User Story

  • I, as the developer, will need to install the required dependencies to manipulate and call upon Entity Framework as well as PostgreSQL functionality.

Acceptance Criteria

  • Upon cloning of repo, the Entity Framework Core as well as the PostgreSQL extension should be installed.
  • Program.cs will need to be modified.

Dependencies

  • These extensions can be installed and implemented before or after test data is seeded. The ERD will need to be created as soon as MVP requirements are understood.

Dev Notes

  • Required Commands
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 6.0

dotnet add package Microsoft.EntityFrameworkCore.Design --version 6.0

dotnet user-secrets init

dotnet user-secrets set "<Name>DbConnectionString" "Host=localhost;Port=5432;Username=postgres;Password=<your_postgresql_password>;Database=CreekRiver"
  • Program.cs Modifications:
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.Json;

// ADDED ABOVE var app = builder.Build() 
// allows passing datetimes without time zone data 
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

// allows our api endpoints to access the database through Entity Framework Core
builder.Services.AddNpgsql<CreekRiverDbContext>(builder.Configuration["CreekRiverDbConnectionString"]);

// Set the JSON serializer options
builder.Services.Configure<JsonOptions>(options =>
{
    options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
    {
        policy.WithOrigins("http://localhost:3000")
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
    });
});

//ADDED AFTER BUILD
app.UseCors();

CREATE a playlist

User Story

As a user, I want to be able to create personalized playlists,enabling me to organize my music according to my preferences and share it with others.

Acceptance Criteria

  • WHEN I access the playlist creation form on the app
  • THEN I should be able to input the name of the playlist, decide if it is public or private, and optionally mark it as a favorite.
  • AND upon submitting the form, the system should create a playlist associated with my account
  • AND I should receive a confirmation that the playlist has been created, along with being redirected to the newly created playlistโ€™s detail page.

Dependencies

  • User authentication must be fully operational and integrated into the API handling to ensure correct user session management.
  • The frontend must provide a form for creating playlists, including handling user input for the name, public/private status, and favorite status.
  • #3 #4

Dev Notes

  • Implement a POST endpoint at /playlists to handle the creation of playlists.
  • Will likely need a PlaylistCreate DTO

Ex. BE Endpoint Code:

    app.MapPost("/playlists", (BE-MusicStreamingDbContext db, PlaylistCreateDto playlistDto) =>
    {
        var newPlaylist = new Playlist
        {
            Name = playlistDto.Name,
            PlaylistImageUid = playlistDto.PlaylistImageUid,
            Public = playlistDto.Public,
            IsFavorite = playlistDto.IsFavorite,  // optionally set by user upon creation
            DateCreated = DateTime.UtcNow,
        };

        db.Playlists.Add(newPlaylist);
        db.SaveChanges();

        return Results.Created($"/playlists/{newPlaylist.PlaylistId}", newPlaylist);
    });
}

Ex. FE code:

const createPlaylist = async (playlistData) => {
    const url = `${endpoint}/playlists`;
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(playlistData)
    });

    if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`Failed to create playlist`);
    }

    return await response.json(); 
};

Remove song from playlist

User Story

As a user I want to be able to remove songs I no longer want on a playlist

Acceptance Criteria

  • When I view a playlist
  • Every song should have a remove from playlist button
  • When I click the button,
  • a modal should appear that asks for confirmation
  • Then when I click yes, the modal should confirm the song has been removed
  • Then when the modal closes, I should see the playlist refreshed to show the song removed

Dependencies

  • db creation

Dev Notes

  • make PATCH call to api/playlists/userId/playlistId passing dto of user id, playlist id, and song id
  • make list of playlists where user id === user id
  • if not null, find playlist in the list where id == playlist id
  • if not null, find song where id == song id
  • if not null, remove selected song from selectedplaylist.songs using .Remove()
  • return results ok

GET all favorite playlists

User Story

As a user, I want to quickly access all my favorite playlists so that I can enjoy my preferred music collections easily.

Acceptance Criteria

  • WHEN I navigate to the favorite playlists section in the app
  • THEN I should see a list of all playlists that I have marked as favorite.

Dependencies

  • User authentication must be completed to ensure that only the logged-in user can access their favorite playlists.
  • The backend must have implemented the isFavorite boolean field in the Playlist table.
  • #3 #4

Dev Notes

  • Implement a GET endpoint that retrieves playlists marked as favorite by the logged-in user.
  • This endpoint should verify user authentication and return only the playlists where isFavorite is true for that user.

Example code for the backend:

 app.MapGet("/playlists/favorites", (BE_MusicStreamingDbContext db, User user) =>
{
    // retrieve favorite playlists for the logged-in user
    var favoritePlaylists = db.Playlists
        .Include(p => p.User)
        .Include(p => p.SongPlaylists).ThenInclude(sp => sp.Song).ThenInclude(s => s.Artist)
        .Where(p => p.IsFavorite && p.UserId == user.Id);

    // select relevant playlist details
    var favoritePlaylistData = favoritePlaylists.Select(p => new
    {
        p.PlaylistId,
        p.Name,
        p.DateCreated,
        p.Public,
        UserName = p.User.Username,
        Songs = p.SongPlaylists.Select(sp => new 
        {
            sp.Song.SongId,
            sp.Song.Name,
            ArtistName = sp.Song.Artist.Name
        })
    }).ToList();

    return Results.Ok(favoritePlaylistData);
});

Code ex. for front end:

const getFavoritePlaylists = () => {
  const url = `${endpoint}/playlists/favorites`;

  return new Promise((resolve, reject) => {
    fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(response => {
        if (!response.ok) {
          throw new Error('Failed to fetch favorite playlists');
        }
        return response.json();
      })
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
};

Get all songs

User Story

As a user making playlists, I need to see what songs are available to choose.

Acceptance Criteria

  • When I am looking at the songs page,
  • I should see a representation of every song available
  • Then when I view the playlist page,
  • I should see a menu of all songs from which to select a song

Dependencies

  • database creation

Dev Notes

  • make GET call to api/songs and return all songs

SETUP - CLASSES + SEEDING TEST DATA

User Story

I, as the developer, must create classes to represent the entities outlined within the ERD to all for Entity Framework to import said entities to PostgreSQL database.

Acceptance Criteria

  • Listed classes should follow the structure and data type of the entities within the provided ERD
  • All tables outside of join tables should refer to their respective classes
  • Artists
  • Song
  • Playlist
  • User

Dependencies

  • N / A, this is one of the first tasks which need to be completed, even before the seeding of test data.

Dev Notes

  • Class Structure, Models > Songs and Playlists
  • Will create the join table between Order and Items
using System.ComponentModel.DataAnnotations;

namespace Bangazon.Models
{
    public class Product
    {
        public int Id { get; set; }
        [Required]
        public string Title { get; set; }
        public string Description { get; set; }
        public string ImageUrl { get; set; }
        public int QuantityAvailable { get; set; }
        public float Price { get; set; }
        public int SellerId { get; set; }
        public int CategoryId { get; set; }
        public ICollection<Order> Orders { get; set; }
    }
}

Examples of utilizing accumulators to generate 'Totals' - CreekRiver:

    public decimal? TotalCost
    {
        get
        {
            if (Campsite?.CampsiteType != null)
            {
                return Campsite.CampsiteType.FeePerNight * TotalNights + _reservationBaseFee;
            }
            return null;
        }
    }
  • Initial Migration:
    NOTE: After cloning and pulling backend repository to their machines, front-end devs will need to invoke ONLY dotnet ef database update. After all subsequent migrations, frontend must run dot net ef database update on all machines.
dotnet ef migrations add InitialCreate
dotnet ef database update

Users - POST

User Story

I, as a user, will need to log in to utilize the application.

Acceptance Criteria

  • Endpoint URL: "/checkuser"
  • As laid out by MVP requirements:
User Authentication: Staff will log in securely using Firebase Authentication, ensuring a reliable and secure access system.

Dependecies

  • All setup tickets will need to be completed before work on this ticket could be done.

Dev Notes

  • A blend between the frontend and the backend; however, it's a process heavily focused on the frontend with useAuth().
  • Involves the creation of a UserDTO
    public class UserDTO
    {
        public string Uid { get; set; }
    }
  • Backend API Call, as utilized in Rare
            app.MapPost("/api/checkuser", (RareDbContext db, UserAuthDto userAuthDto) =>
            {
                var userUid = db.Users.SingleOrDefault(user => user.Uid == userAuthDto.Uid);

                if (userUid == null)
                {
                    return Results.NotFound();
                }
                else
                {
                    return Results.Ok(userUid);
                }
            });

GET playlists by ID

User Story

As a user, I want to be able to access a specific playlist by its ID so that I can view its details.

Acceptance Criteria

  • WHEN I provide a playlist ID / click on details of a playlist
  • THEN I should receive the playlist details including its name, creation date, public status, & songs if the playlist is public or belongs to me.

Dependencies

  • User authentication must be completed to ensure private playlists can only be accessed by their owners.
  • #3 #4 #7

Dev Notes

  • Implement a GET endpoint that retrieves a playlist based on the given ID.
  • The endpoint should check if the playlist is public or a favorite as well.

Ex. BE code:

app.MapGet("/playlists/{playlistId}", (BE_MusicStreamingDbContext db, int playlistId, User user) =>
{
    // Retrieve the playlist based on the provided ID
    var playlist = db.Playlists
        .Include(p => p.SongPlaylists).ThenInclude(sp => sp.Song).ThenInclude(s => s.Artist)
        .FirstOrDefault(p => p.PlaylistId == playlistId);

    if (playlist == null)
    {
        return Results.NotFound("Playlist not found.");
    }

    // Check if the playlist is public or belongs to the current user
    if (!playlist.Public && playlist.UserId != user.Id)
    {
        return Results.Forbidden("You don't have permission to access this playlist.");
    }

    // Return playlist details
    return Results.Ok(new
    {
        PlaylistId = playlist.PlaylistId,
        PlaylistName = playlist.Name,
        DateCreated = playlist.DateCreated,
        IsPublic = playlist.Public,
        IsFavorite = playlist.IsFavorite, 
        Songs = playlist.SongPlaylists.Select(sp => new
        {
            SongId = sp.Song.SongId,
            SongName = sp.Song.Name,
            ArtistName = sp.Song.Artist.Name
        })
    });
});

Ex. FE code:

const getPlaylistById = (playlistId) => {
  const url = `${endpoint}/playlists/${playlistId}`;

  return new Promise((resolve, reject) => {
    fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    })
    .then((response) => {
      if (!response.ok) {
        throw new Error('Failed to fetch playlist details');
      }
      return response.json();
    })
    .then((data) => resolve(data))
    .catch((error) => reject(error));
  });
};

Add song to playlist

User Story

As a user I want to fill my playlist with songs.

Acceptance Criteria

  • When I click the add to playlist button,
  • or select a song from the song menu
  • I should see a modal that confirms the song has been added
  • Then when I navigate to the playlist page, I should see the song on the list

Dependencies

  • db creation

Dev Notes

  • make PATCH call to api/playlists/userId/playlistId passing dto of user id, playlist id, and song id
  • make list of playlists where user id === user id
  • if not null, find playlist in the list where id == playlist id
  • if not null, find song where id == song id
  • if not null, assign selected song to selectedplaylist.songs

Filter songs by genre

User Story

As a user I want to see all songs of a particular genre.

Acceptance Criteria

  • When I view the songs page
  • I should see a button or menu to select genre
  • Then I should see only songs of that genre on the page

Dependencies

db

Dev Notes

  • make GET call to api/songs/genre/genreId
  • make list of songs where genre id == id
  • if not null, return list

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.