From 2e3af5bb0fa93d0fc22adcd13d487af350720f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Mon, 22 Aug 2022 16:35:03 +0200 Subject: [PATCH] Get top artists from API --- assets/app.js | 48 ++++++ src/Controller/ArtistController.php | 51 ++++++ src/Controller/PlaylistController.php | 9 -- templates/playlist-generator/index.html.twig | 161 ++++++++----------- 4 files changed, 169 insertions(+), 100 deletions(-) create mode 100644 src/Controller/ArtistController.php diff --git a/assets/app.js b/assets/app.js index b054960..3d98862 100644 --- a/assets/app.js +++ b/assets/app.js @@ -62,4 +62,52 @@ window.getPlaylists = function () { } }; +/* get artists and update form */ +window.getTopArtists = function () { + var containerElement = document.getElementById("user-top-artists"); + if (containerElement) { + var htmlContent = ""; + + var apiUrl = "artists/top"; + fetch(apiUrl) + .then(function (response) { + return response.json(); + }) + .then(function (data) { + const htmlTemplate = ` + <li class="col"> + <div class="custom-control custom-checkbox"> + <input + type="checkbox" + class="custom-control-input checkbox-artist" + id="check-top-artist-ARTIST_ID" + name="selected-artist[]" + value="ARTIST_ID" + > + <label class="custom-control-label" for="check-top-artist-ARTIST_ID"> + <span class="spotify-image"><img src="ARTIST_IMAGE_URL" style="max-height: 1rem; max-width: 1rem;" /></span> + ARTIST_NAME + </label> + </div> + </li> + `; + + data.forEach((artist) => { + htmlContent += htmlTemplate + .replace(/ARTIST_ID/g, artist["id"]) + .replace(/ARTIST_NAME/g, artist["name"]) + .replace(/ARTIST_IMAGE_URL/g, artist["imageUrl"]); + }); + containerElement.innerHTML = htmlContent; + }) + .catch(function (err) { + console.warn("Something went wrong.", err); + htmlContent = + '<div class="alert alert-warning">Error fetching API data.</div>'; + containerElement.innerHTML = htmlContent; + }); + } +}; + getPlaylists(); +getTopArtists(); diff --git a/src/Controller/ArtistController.php b/src/Controller/ArtistController.php new file mode 100644 index 0000000..4acdd76 --- /dev/null +++ b/src/Controller/ArtistController.php @@ -0,0 +1,51 @@ +<?php + +namespace App\Controller; + +use App\Service\SpotifyApiService; +use App\Service\SpotifyPlaylistService; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; + +class ArtistController extends AbstractController +{ + /** @var SpotifyWebAPI */ + private $spotifyApi; + + public function __construct(SpotifyApiService $spotifyApiService) + { + // increase timeout limit + set_time_limit(60); + + $this->spotifyApi = $spotifyApiService->createApi(); + } + + /** + * @Route("/artists/top", name="get-artists-top") + * + * @return Response + */ + public function getArtists(): Response + { + $rawTopArtists = $this->spotifyApi->getMyTop( + 'artists', + [ + 'limit' => SpotifyPlaylistService::TOP_ARTISTS_COUNT, + 'time_range' => 'short_term' + ] + )->items; + + $artists = []; + foreach ($rawTopArtists as $artist) { + $artists[] = [ + 'id' => $artist->id, + 'name' => $artist->name, + 'imageUrl' => $artist->images[\count($artist->images) - 1]->url, + ]; + } + + return new JsonResponse($artists); + } +} diff --git a/src/Controller/PlaylistController.php b/src/Controller/PlaylistController.php index d5cce8d..6bfd4fd 100644 --- a/src/Controller/PlaylistController.php +++ b/src/Controller/PlaylistController.php @@ -37,17 +37,8 @@ class PlaylistController extends AbstractController { $me = $this->spotifyApi->me(); - $topArtists = $this->spotifyApi->getMyTop( - 'artists', - [ - 'limit' => SpotifyPlaylistService::TOP_ARTISTS_COUNT, - 'time_range' => 'short_term' - ] - )->items; - return $this->render('playlist-generator/index.html.twig', [ 'user' => $me, - 'topArtists' => $topArtists, ]); } diff --git a/templates/playlist-generator/index.html.twig b/templates/playlist-generator/index.html.twig index d15064b..90fe0c5 100644 --- a/templates/playlist-generator/index.html.twig +++ b/templates/playlist-generator/index.html.twig @@ -4,108 +4,87 @@ {% block content %} - {% if topArtists is defined %} - <form class="clearfix mt-2" action="{{ path('generate-quick-playlist') }}"> - <div class="row"> - <div class="col-md-12"> - <legend>Quick playlist generator:</legend> + <form class="clearfix mt-2" action="{{ path('generate-quick-playlist') }}"> + <div class="row"> + <div class="col-md-12"> + <legend>Quick playlist generator:</legend> + </div> + </div> + <div class="row"> + <div class="col-md-6 col-sm-12"> + <div> + <input + type="checkbox" + class="custom-control-input" + id="check-quick-create-long-playlist" + name="check-quick-create-long-playlist" + value="long-playlist" + checked + > + <label class="custom-control-label" for="check-quick-create-long-playlist"> + Generate a long playlist (x2) + </label> </div> </div> - <div class="row"> - <div class="col-md-6 col-sm-12"> - <div> - <input - type="checkbox" - class="custom-control-input" - id="check-quick-create-long-playlist" - name="check-quick-create-long-playlist" - value="long-playlist" - checked - > - <label class="custom-control-label" for="check-quick-create-long-playlist"> - Generate a long playlist (x2) - </label> - </div> + <div class="col-md-6 col-sm-12"> + <div class="btn-group float-end" role="group" aria-label="Action buttons"> + <button name="generate-quick-playlist-from-daily-mixes" type="submit" class="btn btn-secondary">🎶 Mix daily mixes!</button> + <button name="generate-quick-playlist-tambouille-mix" type="submit" class="btn btn-primary">🎶 Pick nice tracks!</button> </div> - <div class="col-md-6 col-sm-12"> - <div class="btn-group float-end" role="group" aria-label="Action buttons"> - <button name="generate-quick-playlist-from-daily-mixes" type="submit" class="btn btn-secondary">🎶 Mix daily mixes!</button> - <button name="generate-quick-playlist-tambouille-mix" type="submit" class="btn btn-primary">🎶 Pick nice tracks!</button> - </div> + </div> + </div> + </form> + + <form class="clearfix mt-2" action="{{ path('generate-playlist-from-top-artists') }}"> + <div class="row"> + <div class="col-md-8 col-sm-12"> + <legend>Generate playlist from artists:</legend> + </div> + <div class="col-md-4 col-sm-12"> + <div class="btn-group float-end" role="group" aria-label="Action buttons"> + <button name="pick-random-artist" type="button" class="btn btn-link" onclick="window.pickRandomArtists()">🎲 Pick random artists</button> </div> </div> - </form> + </div> + <ul class="list-unstyled row row-cols-md-4 row-cols-2" id="user-top-artists"> - <form class="clearfix mt-2" action="{{ path('generate-playlist-from-top-artists') }}"> - <div class="row"> - <div class="col-md-8 col-sm-12"> - <legend>Generate playlist from artists:</legend> + </ul> + <div class="row"> + <div class="col-md-8 col-sm-12"> + <div> + <input + type="checkbox" + class="custom-control-input" + id="check-top-artist-filter-artists" + name="check-top-artist-filter-artists" + value="filter-artists" + checked + > + <label class="custom-control-label" for="check-top-artist-filter-artists"> + Allow only selected artists in recommendations + </label> </div> - <div class="col-md-4 col-sm-12"> - <div class="btn-group float-end" role="group" aria-label="Action buttons"> - <button name="pick-random-artist" type="button" class="btn btn-link" onclick="window.pickRandomArtists()">🎲 Pick random artists</button> - </div> + <div> + <input + type="checkbox" + class="custom-control-input" + id="check-top-artist-long-playlist" + name="check-top-artist-long-playlist" + value="long-playlist" + > + <label class="custom-control-label" for="check-top-artist-long-playlist"> + Generate a long playlist (x2) + </label> </div> </div> - <ul class="list-unstyled row row-cols-md-4 row-cols-2"> - {% for artist in topArtists %} - <li class="col"> - <div class="custom-control custom-checkbox"> - <input - type="checkbox" - class="custom-control-input checkbox-artist" - id="check-top-artist-{{ artist.id }}" - name="selected-artist[]" - value="{{ artist.id }}" - > - <label class="custom-control-label" for="check-top-artist-{{ artist.id }}"> - {% if artist.images is defined %} - {% set artistLastImage = artist.images|last %} - <span class="spotify-image"><img src="{{ artistLastImage.url }}" style="max-height: 1rem; max-width: 1rem;" /></span> - {% endif %} - {{ artist.name }} - </label> - </div> - </li> - {% endfor %} - </ul> - <div class="row"> - <div class="col-md-8 col-sm-12"> - <div> - <input - type="checkbox" - class="custom-control-input" - id="check-top-artist-filter-artists" - name="check-top-artist-filter-artists" - value="filter-artists" - checked - > - <label class="custom-control-label" for="check-top-artist-filter-artists"> - Allow only selected artists in recommendations - </label> - </div> - <div> - <input - type="checkbox" - class="custom-control-input" - id="check-top-artist-long-playlist" - name="check-top-artist-long-playlist" - value="long-playlist" - > - <label class="custom-control-label" for="check-top-artist-long-playlist"> - Generate a long playlist (x2) - </label> - </div> - </div> - <div class="col-md-4 col-sm-12"> - <div class="btn-group float-end" role="group" aria-label="Action buttons"> - <button name="generate-playlist-random-top-artists" type="submit" class="btn btn-secondary">🎲 Random!</button> - <button name="generate-playlist-top-artists" type="submit" class="btn btn-primary">🎶 Generate!</button> - </div> + <div class="col-md-4 col-sm-12"> + <div class="btn-group float-end" role="group" aria-label="Action buttons"> + <button name="generate-playlist-random-top-artists" type="submit" class="btn btn-secondary">🎲 Random!</button> + <button name="generate-playlist-top-artists" type="submit" class="btn btn-primary">🎶 Generate!</button> </div> </div> - </form> - {% endif %} + </div> + </form> <form class="clearfix" action="{{ path('generate-playlist-from-playlists') }}"> <legend>Generate playlist from tracks in existing playlist:</legend> -- GitLab