feat: song likes and initial implementation of Spotify playlist support, refs #9
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<th>Song</th>
|
||||
<th>Submitter</th>
|
||||
<th>Details</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@foreach(var songSuggestion in Model.SongSuggestions)
|
||||
{
|
||||
@@ -26,6 +27,17 @@
|
||||
<td><a href="@songSuggestion?.Song.Url" target="_blank">@string.Format("{0} - {1}", songSuggestion?.Song.Name, songSuggestion?.Song.Artist)</a></td>
|
||||
<td>@displayName</td>
|
||||
<td><a href="/SongSubmission/@songSuggestion?.Id">View</a></td>
|
||||
<td class="=viewLike">
|
||||
@if(songSuggestion?.Song != null)
|
||||
{
|
||||
var handler = Model.HasUserLikedThisSong(@songSuggestion.Song) ? "UnlikeSong" : "LikeSong";
|
||||
var likebuttonText = Model.HasUserLikedThisSong(@songSuggestion.Song) ? "Unlike" : "Like";
|
||||
<form method="post">
|
||||
<input name="songId" value="@songSuggestion.Song.SongId" type="hidden" />
|
||||
<input type="submit" id="songlike" value="@likebuttonText" asp-page-handler="@handler" />
|
||||
</form>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
@@ -17,14 +17,67 @@ public class IndexModel : PageModel
|
||||
[BindProperty]
|
||||
public List<SongSuggestion> SongSuggestions { get; set; } = new List<SongSuggestion>();
|
||||
|
||||
public Task OnGet()
|
||||
{
|
||||
private User _currentUser;
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get {
|
||||
if(_currentUser == null)
|
||||
{
|
||||
var userName = this.User.Identity.Name;
|
||||
using(var dci = DataContext.Instance)
|
||||
{
|
||||
_currentUser = dci.Users.Include(u => u.LikedSongs).Where(u => u.LdapUserName == userName).SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
return _currentUser;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool HasUserLikedThisSong(Song song)
|
||||
{
|
||||
return CurrentUser.LikedSongs.Where(s => s.SongId == song.SongId).FirstOrDefault() != default(Song);
|
||||
}
|
||||
|
||||
public Task OnGet()
|
||||
{
|
||||
using var dci = DataContext.Instance;
|
||||
SongSuggestions = dci.SongSuggestions.OrderByDescending(s => s.Date)
|
||||
.Take(50)
|
||||
.Include(s => s.Song)
|
||||
.Include(s => s.User)
|
||||
.ToList();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
.ToList();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostLikeSong(int? songId)
|
||||
{
|
||||
using (var dci = DataContext.Instance)
|
||||
{
|
||||
var user = dci.Users.Include(u => u.LikedSongs).Where(u => u.UserId == CurrentUser.UserId).SingleOrDefault();
|
||||
if (user.LikedSongs.Find(s => s.SongId == songId) == default(Song))
|
||||
{
|
||||
user.LikedSongs.Add(dci.Songs.Find(songId));
|
||||
await dci.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
return RedirectToPage("/");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostUnlikeSong(int? songId)
|
||||
{
|
||||
using(var dci = DataContext.Instance)
|
||||
{
|
||||
var user = dci.Users.Include(u => u.LikedSongs).Where(u => u.UserId == CurrentUser.UserId).SingleOrDefault();
|
||||
var songToRemove = user.LikedSongs.Where(s => s.SongId == songId).SingleOrDefault();
|
||||
if (songToRemove != default(Song))
|
||||
{
|
||||
user.LikedSongs.Remove(songToRemove);
|
||||
await dci.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
return RedirectToPage("/");
|
||||
}
|
||||
}
|
||||
|
@@ -23,9 +23,15 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
var userName = User.Identity.Name;
|
||||
var dci = DataContext.Instance;
|
||||
var selectedUsers = dci.Users.Where(u => u.LdapUserName == userName);
|
||||
var userId = selectedUsers.SingleOrDefault()?.UserId;
|
||||
dci.Dispose();
|
||||
|
||||
<form method="post" action="Auth/Logout">
|
||||
<div>
|
||||
Welcome, @User.Identity.Name!
|
||||
Welcome, <a href="/User/@userId">@User.Identity.Name</a>!
|
||||
</div>
|
||||
<div>
|
||||
<input name="submit" type="submit" value="Logout" />
|
||||
|
@@ -14,6 +14,7 @@
|
||||
<th>Suggestion</th>
|
||||
<th>Song</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@foreach(var submission in Model.UserSongSubmissions)
|
||||
{
|
||||
@@ -44,6 +45,17 @@
|
||||
}
|
||||
<button class=@buttonClass onclick="redirectTo(@submission.Id)">@buttonText</button>
|
||||
</td>
|
||||
<td class="=viewLike">
|
||||
@if(submission.Song != null)
|
||||
{
|
||||
var handler = Model.HasUserLikedThisSong(submission.Song) ? "UnlikeSong" : "LikeSong";
|
||||
var likebuttonText = Model.HasUserLikedThisSong(submission.Song) ? "Unlike" : "Like";
|
||||
<form method="post">
|
||||
<input name="songId" value="@submission.Song.SongId" type="hidden" />
|
||||
<input type="submit" id="songlike" value="@likebuttonText" asp-page-handler="@handler" />
|
||||
</form>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
@@ -53,8 +65,8 @@ else
|
||||
{
|
||||
<div class="text-left">
|
||||
<div class="suggestionHelper">
|
||||
<div class="title">Today's suggestionHelper is: <b>@Model.SuggestionHelper.Title</b></div>
|
||||
<div class="description" style="font-style: italic;">@Model.SuggestionHelper.Description</div>
|
||||
<div class="title">Today's suggestionHelper is: <b>@Model.SuggestionHelper?.Title</b></div>
|
||||
<div class="description" style="font-style: italic;">@Model.SuggestionHelper?.Description</div>
|
||||
</div>
|
||||
<form method="post">
|
||||
<label asp-for="SubmitUrl" >Song Url:</label>
|
||||
|
@@ -75,6 +75,24 @@ public class SongSubmissionModel : PageModel
|
||||
}
|
||||
}
|
||||
|
||||
private User _currentUser;
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get {
|
||||
if(_currentUser == null)
|
||||
{
|
||||
var userName = this.User.Identity.Name;
|
||||
using(var dci = DataContext.Instance)
|
||||
{
|
||||
_currentUser = dci.Users.Include(u => u.LikedSongs).Where(u => u.LdapUserName == userName).SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
return _currentUser;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<SpotifyAPI.Web.FullTrack> SpotifySuggestions
|
||||
{
|
||||
@@ -115,6 +133,11 @@ public class SongSubmissionModel : PageModel
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public bool HasUsedSuggestion { get; set; } = true;
|
||||
|
||||
public bool HasUserLikedThisSong(Song song)
|
||||
{
|
||||
return CurrentUser.LikedSongs.Where(s => s.SongId == song.SongId).FirstOrDefault() != default(Song);
|
||||
}
|
||||
|
||||
private async Task UpdateGroup(SongSuggestion suggestion)
|
||||
{
|
||||
var isItToday = suggestion.Date.Date == DateTime.Today;
|
||||
@@ -223,6 +246,35 @@ public class SongSubmissionModel : PageModel
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostLikeSong(int? songId)
|
||||
{
|
||||
using (var dci = DataContext.Instance)
|
||||
{
|
||||
var user = dci.Users.Include(u => u.LikedSongs).Where(u => u.UserId == CurrentUser.UserId).SingleOrDefault();
|
||||
if (user.LikedSongs.Find(s => s.SongId == songId) == default(Song))
|
||||
{
|
||||
user.LikedSongs.Add(dci.Songs.Find(songId));
|
||||
await dci.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
return RedirectToPage("SongSubmission");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostUnlikeSong(int? songId)
|
||||
{
|
||||
using(var dci = DataContext.Instance)
|
||||
{
|
||||
var user = dci.Users.Include(u => u.LikedSongs).Where(u => u.UserId == CurrentUser.UserId).SingleOrDefault();
|
||||
var songToRemove = user.LikedSongs.Where(s => s.SongId == songId).SingleOrDefault();
|
||||
if (songToRemove != default(Song))
|
||||
{
|
||||
user.LikedSongs.Remove(songToRemove);
|
||||
await dci.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
return RedirectToPage("SongSubmission");
|
||||
}
|
||||
|
||||
public IActionResult OnGetUpdate()
|
||||
{
|
||||
var songUrl = Request.Query["SubmitUrl"];
|
||||
|
@@ -1,4 +1,5 @@
|
||||
@page "{userIndex}"
|
||||
|
||||
@model UserModel
|
||||
@{
|
||||
ViewData["Title"] = "User #" + @Model.userId;
|
||||
@@ -12,6 +13,20 @@
|
||||
<label asp-for="UserName">Contact Name</label>
|
||||
<input asp-for="UserName" disabled />
|
||||
<br />
|
||||
<input type="submit" title="Submit" />
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
@if(@Model.IsSpotifyAuthenticated)
|
||||
{
|
||||
<form method="post" >
|
||||
<input name="userIndex" value="@Model.userId" type="hidden" />
|
||||
<input type="submit" value="Deauthorize Spotify" asp-page-handler="SpotifyLogout" />
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<form method="post" >
|
||||
<input name="userIndex" value="@Model.userId" type="hidden" />
|
||||
<input type="submit" value="Connect to Spotify" asp-page-handler="SpotifyLogin" />
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
|
@@ -1,5 +1,8 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using SpotifyAPI.Web;
|
||||
using System.Web;
|
||||
|
||||
namespace sotd.Pages;
|
||||
|
||||
@@ -18,10 +21,12 @@ public class UserModel : PageModel
|
||||
|
||||
public string UserName { get; set; }
|
||||
|
||||
public bool IsSpotifyAuthenticated { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string UserNickName { get; set; }
|
||||
|
||||
public void OnGet(int userIndex)
|
||||
public async Task OnGet(int userIndex, [FromServices] SpotifyApiClient spotifyClient)
|
||||
{
|
||||
using (var dci = DataContext.Instance)
|
||||
{
|
||||
@@ -29,10 +34,11 @@ public class UserModel : PageModel
|
||||
this.UserName = user == null ? string.Empty : (user.Name ?? string.Empty);
|
||||
this.UserNickName = user == null ? string.Empty : (user.NickName ?? string.Empty);
|
||||
this.userId = userIndex;
|
||||
this.IsSpotifyAuthenticated = await spotifyClient.IsUserAuthenticatedAsync(user);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPost(int userIndex)
|
||||
public async Task OnPost(int userIndex, [FromServices] SpotifyApiClient spotifyClient)
|
||||
{
|
||||
using (var dci = DataContext.Instance)
|
||||
{
|
||||
@@ -42,6 +48,39 @@ public class UserModel : PageModel
|
||||
user.NickName = this.UserNickName;
|
||||
dci.SaveChanges();
|
||||
this.UserName = user.Name ?? string.Empty;
|
||||
this.IsSpotifyAuthenticated = await spotifyClient.IsUserAuthenticatedAsync(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult OnPostSpotifyLogin(int userIndex, string currentUri, [FromServices] SpotifyApiClient spotifyClient)
|
||||
{
|
||||
_logger.LogTrace($"Attempting Spotify login for user with id {userIndex}.");
|
||||
|
||||
var loginRequest = new LoginRequest(
|
||||
new Uri(spotifyClient.GetLoginRedirectUri()),
|
||||
AppConfiguration.Instance.SpotifyClientId,
|
||||
LoginRequest.ResponseType.Code)
|
||||
{
|
||||
Scope = new[] { Scopes.PlaylistReadPrivate, Scopes.PlaylistReadCollaborative, Scopes.PlaylistModifyPrivate, Scopes.PlaylistModifyPublic, Scopes.UgcImageUpload }
|
||||
};
|
||||
var redirectUri = loginRequest.ToUri().ToString() + $"&finalRedirect={HttpUtility.UrlEncode($"{Request.Scheme}://{Request.Host}:{Request.Host.Port ?? 80}{Request.Path}")}";
|
||||
|
||||
return this.Redirect(redirectUri);
|
||||
}
|
||||
|
||||
public async Task OnPostSpotifyLogout(int userIndex, [FromServices] SpotifyApiClient spotifyClient)
|
||||
{
|
||||
_logger.LogTrace($"Attempting to deauthorize Spotify for user with id {userIndex}.");
|
||||
|
||||
using (var dci = DataContext.Instance)
|
||||
{
|
||||
var user = dci.Users?.Find(userIndex);
|
||||
if (user != null)
|
||||
{
|
||||
await spotifyClient.DeAuthorizeUserAsync(user);
|
||||
user.NickName = this.UserNickName;
|
||||
this.UserName = user.Name ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user