Add a popularity modal to the page when clicking on the popularity value (finishes #5 )
This commit is contained in:
parent
7ea4f89522
commit
4a61eec9ff
11 changed files with 205 additions and 19 deletions
15
app.js
15
app.js
|
|
@ -8,7 +8,14 @@ let app = new Vue({
|
|||
show: {
|
||||
popularity_popup: false,
|
||||
popularity_hover: false,
|
||||
follower_hover: false
|
||||
follower_hover: false,
|
||||
modal_content: false,
|
||||
modal: {
|
||||
popularity: false,
|
||||
track: false,
|
||||
artist: false,
|
||||
playlist_export: false,
|
||||
}
|
||||
},
|
||||
error: {
|
||||
main: ``,
|
||||
|
|
@ -67,5 +74,11 @@ let app = new Vue({
|
|||
})
|
||||
},
|
||||
get_data: fetch_data,
|
||||
hide_modal: function () {
|
||||
this.show.modal.popularity = false;
|
||||
this.show.modal.track = false;
|
||||
this.show.modal.artist = false;
|
||||
this.show.modal.playlist_export = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="card">
|
||||
<div class="image">
|
||||
<img v-id="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
|
||||
<img v-if="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
|
||||
<div class="missing-image" v-else>
|
||||
<music-note colour="#1DB954"></music-note>
|
||||
</div>
|
||||
|
|
@ -12,6 +12,6 @@
|
|||
<br>
|
||||
<span class="subtitle">{{genres}}</span>
|
||||
</div>
|
||||
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip">{{artist.popularity}}</div>
|
||||
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count}}</div>
|
||||
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{artist.popularity}}</div>
|
||||
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count.toLocaleString()}}</div>
|
||||
</div>
|
||||
|
|
@ -17,9 +17,14 @@ Vue.component(
|
|||
return genres.join(`, `);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show_popularity_modal: function () {
|
||||
this.$emit(`popularity_click`)
|
||||
}
|
||||
},
|
||||
template: `<div class="card">
|
||||
<div class="image">
|
||||
<img v-id="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
|
||||
<img v-if="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
|
||||
<div class="missing-image" v-else>
|
||||
<music-note colour="#1DB954"></music-note>
|
||||
</div>
|
||||
|
|
@ -31,8 +36,8 @@ Vue.component(
|
|||
<br>
|
||||
<span class="subtitle">{{genres}}</span>
|
||||
</div>
|
||||
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip">{{artist.popularity}}</div>
|
||||
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count}}</div>
|
||||
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{artist.popularity}}</div>
|
||||
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count.toLocaleString()}}</div>
|
||||
</div>`
|
||||
}
|
||||
)
|
||||
|
|
@ -4,4 +4,13 @@ Vue.component(
|
|||
props: [ `colour` ],
|
||||
template: `<svg width="72" height="72" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" fill="none" rx="0" ry="0"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M17.4911 2.11667L21.4511 4.09667C21.9411 4.34667 22.1411 4.93667 21.8911 5.43667C21.6411 5.93667 21.0411 6.13667 20.5511 5.88667L18.0011 4.61667L17.9911 16.4367C17.9911 16.4467 17.9936 16.4567 17.9961 16.4667C17.9986 16.4767 18.0011 16.4867 18.0011 16.4967C18.0011 18.4267 16.4311 19.9967 14.5011 19.9967C12.5711 19.9967 11.0011 18.4267 11.0011 16.4967C11.0011 14.5667 12.5711 12.9967 14.5011 12.9967C15.0411 12.9967 15.5411 13.1267 16.0011 13.3467L16.0111 3.10667C15.9911 2.99667 16.0011 2.87667 16.0311 2.75667C16.1711 2.14667 16.9411 1.80667 17.4911 2.11667ZM12.8911 5.43664C12.6511 5.93664 12.0511 6.13664 11.5511 5.88664L9.0011 4.61664L8.9911 18.4366C8.9911 18.4466 8.9936 18.4566 8.9961 18.4666C8.9986 18.4766 9.0011 18.4866 9.0011 18.4966C9.0011 20.4266 7.4311 21.9966 5.5011 21.9966C3.5711 21.9966 2.0011 20.4266 2.0011 18.4966C2.0011 16.5666 3.5711 14.9966 5.5011 14.9966C6.0411 14.9966 6.5411 15.1266 7.0011 15.3466L7.0111 3.10664C6.9911 2.99664 7.0011 2.87664 7.0311 2.76664C7.1711 2.14664 7.9411 1.81664 8.4911 2.12664L12.4411 4.09664C12.9411 4.34664 13.1411 4.94664 12.8911 5.43664Z" :fill="colour || '#ffffff'"></path></svg>`
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
Vue.component(
|
||||
`close`,
|
||||
{
|
||||
props: [ `colour` ],
|
||||
template: `<svg width="72" height="72" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" fill="none" rx="0" ry="0"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M13.4049 12.0025L18.6949 6.7125C19.0849 6.3225 19.0849 5.6925 18.6949 5.3025C18.3049 4.9125 17.6749 4.9125 17.2849 5.3025L11.9949 10.5925L6.70494 5.2925C6.31494 4.9025 5.68494 4.9025 5.29494 5.2925C4.90494 5.6825 4.90494 6.3125 5.29494 6.7025L10.5849 12.0025L5.29494 17.2925C4.90494 17.6825 4.90494 18.3125 5.29494 18.7025C5.48494 18.9025 5.73494 19.0025 5.99494 19.0025C6.25494 19.0025 6.50494 18.9025 6.70494 18.7125L11.9949 13.4125L17.2849 18.7025C17.4849 18.9025 17.7349 19.0025 17.9949 19.0025C18.2549 19.0025 18.5049 18.9025 18.7049 18.7125C19.0949 18.3225 19.0949 17.6925 18.7049 17.3025L13.4049 12.0025Z" :fill="colour || '#ffffff'"></path></svg>`
|
||||
}
|
||||
)
|
||||
|
|
@ -17,6 +17,6 @@
|
|||
<br>
|
||||
<span class="subtitle" v-html="artists"></span>
|
||||
</div>
|
||||
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip">{{track.popularity}}</div>
|
||||
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{track.popularity}}</div>
|
||||
<div class="duration bottom right corner">{{duration}}</div>
|
||||
</div>
|
||||
|
|
@ -39,6 +39,11 @@ Vue.component(
|
|||
return artists.join(`, `)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
show_popularity_modal: function () {
|
||||
this.$emit('popularity_click')
|
||||
}
|
||||
},
|
||||
template: `<div class="card">
|
||||
<div class="image">
|
||||
<a v-if="track.album.image.url" :href="track.album.link" target="_blank" rel="noopener">
|
||||
|
|
@ -58,7 +63,7 @@ Vue.component(
|
|||
<br>
|
||||
<span class="subtitle" v-html="artists"></span>
|
||||
</div>
|
||||
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip">{{track.popularity}}</div>
|
||||
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{track.popularity}}</div>
|
||||
<div class="duration bottom right corner">{{duration}}</div>
|
||||
</div>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@ div.card .bottom { bottom: 0; }
|
|||
|
||||
|
||||
/* border-radius: top-left top-right lower-right lower-left */
|
||||
div.card .popularity { border-radius: 0 var(--border-radius) 0 var(--border-radius); }
|
||||
div.card .popularity {
|
||||
border-radius: 0 var(--border-radius) 0 var(--border-radius);
|
||||
cursor: pointer;
|
||||
}
|
||||
div.card .followers,
|
||||
div.card .duration { border-radius: var(--border-radius) 0 var(--border-radius) 0; }
|
||||
|
||||
|
|
|
|||
56
css/modal.css
Normal file
56
css/modal.css
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
div.modal-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
background-color: var(--modal-container-background);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.modal {
|
||||
z-index: 6;
|
||||
width: 90%;
|
||||
max-height: 85%;
|
||||
background-color: var(--modal-background);
|
||||
border-radius: 5px;
|
||||
padding: 0 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.modal * { color: var(--modal-text); }
|
||||
|
||||
div.modal h2 { margin-top: 30px; }
|
||||
|
||||
div.modal p { padding: 0px 5px 15px 5px; }
|
||||
|
||||
div.modal .close-modal {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
color: var(--spotify-green);
|
||||
}
|
||||
div.modal .close-modal:hover {
|
||||
color: var(--error);
|
||||
transform: scale(1.2, 1.2);
|
||||
transition: ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media only screen and (min-width: 768px) {
|
||||
div.modal {
|
||||
width: 50%;
|
||||
max-height: 75%;
|
||||
}
|
||||
div.modal h2 {
|
||||
margin-top: 19.920px;
|
||||
}
|
||||
}
|
||||
62
css/transitions.css
Normal file
62
css/transitions.css
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Transition for modal background appearing/disappearing */
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Transition for modal card appearing disappearing */
|
||||
.burst-enter-active {
|
||||
animation: burst-in .5s;
|
||||
}
|
||||
.burst-leave-active { animation: burst-out .5s; }
|
||||
|
||||
@keyframes burst-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes burst-out {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media only screen and (min-width: 768px) {
|
||||
@keyframes burst-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes burst-out {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
index.html
40
index.html
|
|
@ -9,9 +9,11 @@
|
|||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@800&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="./css/card.css">
|
||||
<link rel="stylesheet" href="./css/modal.css">
|
||||
<link rel="stylesheet" href="./css/transitions.css">
|
||||
|
||||
<!-- Javascript Imports -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
|
||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<script src="./components/artist.js" defer async></script>
|
||||
<script src="./components/track.js" defer async></script>
|
||||
|
|
@ -68,20 +70,44 @@
|
|||
v-for="top_track in data.tracks"
|
||||
:track="top_track"
|
||||
:key="top_track.id"
|
||||
@popularity_click="show.modal.popularity = true"
|
||||
></track-card>
|
||||
</div>
|
||||
<div class="body" v-if="data.artists.length > 0">
|
||||
<artist
|
||||
v-for="top_artist in data.artists"
|
||||
:artist="top_artist"
|
||||
:key="top_artist.id"
|
||||
v-for="top_artist in data.artists"
|
||||
:artist="top_artist"
|
||||
:key="top_artist.id"
|
||||
@popularity_click="show.modal.popularity = true"
|
||||
></artist>
|
||||
</div>
|
||||
|
||||
<!-- Modals Needed -->
|
||||
<div v-if="show.modal.track" class="modal track-modal"></div>
|
||||
<div v-if="show.modal.popularity" class="modal info-modal"></div>
|
||||
<div v-if="show.modal.playlist_export" class="modal playlist-export-modal"></div>
|
||||
<transition name="fade" @after-enter="show.modal_content = true">
|
||||
<div
|
||||
v-if="Object.values(this.show.modal).includes(true)"
|
||||
class="modal-container"
|
||||
@click.self="show.modal_content = false"
|
||||
>
|
||||
<transition name="burst" @after-leave="hide_modal">
|
||||
<div v-if="show.modal_content && show.modal.popularity" class="modal">
|
||||
<span @click="show.modal_content = false">
|
||||
<close class="close-modal" colour="#ffffff80" @click="show.modal_content = false"></close>
|
||||
</span>
|
||||
<h2 class="center">How is Popularity Calculated?</h2>
|
||||
<p class="center">
|
||||
Popularity is a value between 0 and 100 that is calculated by Spotify based on how many plays the song/artist has recieved and how recent those plays are.
|
||||
</p>
|
||||
<p class="center">
|
||||
This means that an artist/song that has had 100 plays today will have a higher popularity than a song/artist that has 100 from a month ago.
|
||||
</p>
|
||||
<p class="center">
|
||||
This number is not updated in real time so refreshing the page will not reflect it's absolute accurate value.
|
||||
</p>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@
|
|||
--on-card-colour: #4c4c4c;
|
||||
--on-card-text: var(--spotify-green);
|
||||
|
||||
--modal-container-background: #0e0f10eb;
|
||||
--modal-background: var(--card-colour);
|
||||
--modal-text: var(--card-text);
|
||||
|
||||
--fonts: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +143,7 @@ div.body {
|
|||
border-width: 2px;
|
||||
}
|
||||
|
||||
div.login > div {
|
||||
div#login > div {
|
||||
display: inline-block;
|
||||
color: var(--card-text);
|
||||
padding: 20px;
|
||||
|
|
@ -286,4 +290,7 @@ div.login > div {
|
|||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
div#login > div {
|
||||
width: 33%;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue