Playlist-element

This commit is contained in:
Kasper Rynning-Tønnesen
2019-11-16 21:32:43 +01:00
parent 6b40947302
commit a06f965163
7 changed files with 8122 additions and 20 deletions

View File

@@ -0,0 +1,95 @@
<template>
<div class="context-menu-container" :style="'top:' + mouseY + 'px;left:' + mouseX + 'px;'">
<ul>
<li>Copy link</li>
<li>Find similar</li>
<li>Added by {{ addedBy }}</li>
<hr />
<li>Delete</li>
</ul>
<div class="context-menu-background" @mouseout="closeSelf" @click="closeSelf"></div>
</div>
</template>
<script>
export default {
props: {
id: {
required: true,
type: String
},
type: {
required: true,
type: String
},
addedBy: {
required: true,
type: String
},
mouseX: {
required: true,
type: Number
},
mouseY: {
required: true,
type: Number
}
},
methods: {
closeSelf: function(e) {
if (e.toElement == null || e.toElement.nodeName == null) {
return;
}
if (e.toElement.nodeName == "UL" || e.toElement.nodeName == "LI") {
return;
}
this.$emit("closeContextMenu");
}
}
};
</script>
<style scoped lang="scss">
.context-menu-background {
background: #000000a0;
width: 500px;
height: 500px;
position: absolute;
left: -85%;
top: -100%;
z-index: 1;
}
.context-menu-container {
font-family: sans-serif;
position: absolute;
background-color: #2d2d2d;
border-radius: 10px;
color: white;
& ul {
z-index: 2;
list-style: none;
padding: 10px 0 10px 0;
margin: 0;
position: relative;
background-color: #2d2d2d;
border-radius: 10px;
color: white;
& li {
cursor: pointer;
padding: 5px 15px;
&:hover {
background-color: #ffffff15;
}
}
& hr {
padding: 0px;
margin: 0;
}
}
}
</style>

View File

@@ -0,0 +1,144 @@
<template>
<div class="playlist-conatiner">
<div class="song-container" v-for="(song, i) in paginatedList" :key="i">
<Song
class="song"
:title="song.title"
:thumbnail="song.thumbnail"
:votes="song.votes"
:addedBy="song.added_by"
:id="song.id"
:type="song.type"
@contextmenu="moreInfo"
/>
<div class="song-context-button" @click="moreInfo($event, song.id)">more</div>
</div>
<div class="pagination-buttons">
<button @click="firstPage" :disabled="disabledPrev" class="first"><</button>
<button @click="prevPage" :disabled="disabledPrev">previous</button>
<span>{{ page + 1 }} / {{ pages }}</span>
<button @click="nextPage" :disabled="disabledNext">next</button>
<button @click="lastPage" :disabled="disabledNext" class="last">></button>
</div>
<ContextMenu
v-if="contextMenuOpen"
:addedBy="contextOnElement.added_by"
:id="contextOnElement.id"
:type="contextOnElement.type"
:mouseX="mouseX"
:mouseY="mouseY"
@closeContextMenu="closeContextMenu"
/>
</div>
</template>
<script>
import Song from "@/components/playlist/Song";
import ContextMenu from "@/components/playlist/ContextMenu";
export default {
components: {
Song,
ContextMenu
},
computed: {
paginatedList: function() {
return this.playlist.slice(
this.page * this.perPage,
(1 + this.page) * this.perPage
);
},
disabledPrev: function() {
return this.page == 0;
},
disabledNext: function() {
return this.playlist.length < (this.page + 1) * this.perPage;
},
pages: function() {
return Math.ceil(this.playlist.length / this.perPage);
}
},
async beforeMount() {
const request = await fetch("https://zoff.me/api/list/summér", {
method: "POST"
});
const playlist = await request.json();
if (this.playlist.error == true) {
console.error(this.playlist.error);
return;
}
this.playlist = playlist.results;
},
methods: {
moreInfo: function(e, id) {
e.preventDefault();
this.contextOnElement = this.playlist.find(song => song.id == id);
this.mouseX = e.pageX;
this.mouseY = e.pageY;
this.contextMenuOpen = true;
},
closeContextMenu: function() {
this.contextMenuOpen = false;
this.contextOnElement = null;
},
firstPage: function() {
this.page = 0;
},
lastPage: function() {
this.page = Math.floor(this.playlist.length / this.perPage);
},
prevPage: function() {
if (this.page == 0) {
return;
}
this.page -= 1;
},
nextPage: function() {
if (this.playlist.length < (this.page + 1) * this.perPage) {
return;
}
this.page += 1;
}
},
data() {
return {
contextMenuOpen: false,
contextOnElement: {},
page: 0,
perPage: 10,
playlist: []
};
}
};
</script>
<style scoped lang="scss">
.song-container {
display: flex;
flex-direction: row;
& .song {
width: 75%;
}
& .song-context-button {
width: 25%;
display: flex;
justify-content: center;
align-items: center;
}
}
.pagination-buttons {
display: flex;
justify-content: space-between;
& button {
width: 35%;
height: 30px;
&.first,
&.last {
width: 10%;
}
}
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div class="song-container">
<div class="song-voteable-container" @click="clickedSong" @contextmenu="$emit('contextmenu', $event, id)">
<div class="song-thumbnail">
<img :src="thumbnail" :alt="title" />
</div>
<div class="song-info">
<div class="song-title">{{ title }}</div>
<div class="song-votes">{{ votes }} vote{{votes > 1 ? "s" : null }}</div>
</div>
</div>
</div>
</template>
<script>
import ContextMenu from "@/components/playlist/ContextMenu";
export default {
components: {
ContextMenu
},
props: {
id: {
required: true,
type: String
},
thumbnail: {
required: true,
type: String
},
title: {
required: true,
type: String
},
votes: {
required: true,
type: Number
},
addedBy: {
required: true,
type: String
},
type: {
required: true,
type: String
}
},
data() {
return {
contextMenuOpen: false,
mouseX: 0,
mouseY: 0
};
},
methods: {
clickedSong: function() {
console.log("Clicked on song with info", this.title, this.id);
},
}
};
</script>
<style scoped lang="scss">
.song-container {
display: flex;
flex-direction: row;
.song-voteable-container {
width: 75%;
display: flex;
& .song-thumbnail {
width: 25%;
& img {
width: 100%;
border-top-left-radius: 7.5px;
border-bottom-left-radius: 7.5px;
}
}
& .song-info {
width: 100%;
padding-left: 10px;
display: flex;
justify-content: space-evenly;
flex-direction: column;
}
}
& .song-mutation {
width: 25%;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>