style: added new release style; refactor: Artist page with composition API (to finish); refactor: extracted new release check logic

This commit is contained in:
Roberto Tonino 2020-11-14 22:27:47 +01:00
parent d04439857a
commit ced8650ee6
9 changed files with 139 additions and 98 deletions

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,7 @@
<li
v-for="(item, name) in artistReleases"
:key="name"
class="section-tabs__tab"
class="section-tabs__tab uppercase-first-letter"
@click="changeTab(name)"
:class="{ active: currentTab === name }"
>
@ -33,6 +33,7 @@
:key="data.title"
@click="data.sortKey ? sortBy(data.sortKey) : null"
:style="{ width: data.width ? data.width : 'auto' }"
class="uppercase-first-letter"
:class="{
'sort-asc': data.sortKey == sortKey && sortOrder == 'asc',
'sort-desc': data.sortKey == sortKey && sortOrder == 'desc',
@ -46,8 +47,8 @@
</tr>
</thead>
<tbody>
<tr v-for="release in showTable">
<router-link
<tr v-for="release in sortedData" :key="release.releaseID">
<RouterLink
tag="td"
class="flex items-center clickable"
:to="{ name: 'Album', params: { id: release.releaseID } }"
@ -57,12 +58,17 @@
:src="release.releaseCover"
style="margin-right: 16px; width: 56px; height: 56px"
/>
<i v-if="release.isReleaseExplicit" class="material-icons explicit-icon">explicit</i>
<i v-if="release.isReleaseExplicit" class="material-icons title-icon title-icon--explicit">explicit</i>
{{ release.releaseTitle }}
<i v-if="checkNewRelease(release.releaseDate)" class="material-icons" style="color: #ff7300">fiber_new</i>
</router-link>
<td>{{ release.releaseDate }}</td>
<td>{{ release.releaseTracksNumber }}</td>
<i
v-if="checkNewRelease(release.releaseDate)"
class="material-icons title-icon title-icon--new title-icon--right"
>
fiber_new
</i>
</RouterLink>
<td class="text-center">{{ release.releaseDate }}</td>
<td class="text-center">{{ release.releaseTracksNumber }}</td>
<td @click.stop="sendAddToQueue(release.releaseLink)" class="clickable">
<i class="material-icons" :title="$t('globals.download_hint')"> file_download </i>
</td>
@ -73,80 +79,75 @@
</template>
<script>
import { defineComponent, ref, unref, reactive, computed, onMounted, toRefs } from '@vue/composition-api'
import { orderBy } from 'lodash-es'
import { socket } from '@/utils/socket'
import { sendAddToQueue } from '@/utils/downloads'
import EventBus from '@/utils/EventBus'
import { formatArtistData } from '@/data/artist'
import { checkNewRelease } from '@/utils/dates'
import { formatArtistData, getArtistData } from '@/data/artist'
import { standardizeData } from '@/data/standardize'
import { ref, reactive, computed, onMounted, toRefs, onDeactivated } from '@vue/composition-api'
export default {
setup() {
export default defineComponent({
setup(props, ctx) {
const state = reactive({
currentTab: '',
sortKey: 'releaseDate',
sortOrder: 'desc',
artistReleases: {},
artistID: '',
artistName: '',
artistPicture: ''
artistPicture: '',
currentRelease: computed(() => state.artistReleases[state.currentTab])
})
const currentRelease = computed(() => state.artistReleases[state.currentTab])
const artistID = computed(() => ctx.root.$router.currentRoute.params.id)
const hasDataLoaded = ref(false)
getArtistData(unref(artistID))
.then(artistData => {
hasDataLoaded.value = true
const setupData = data => {
const {
data: [{ artistID, artistName, artistPictureXL, artistReleases }]
} = standardizeData({ data: [data], hasLoaded: true }, formatArtistData)
data: [{ artistName, artistPictureXL, artistReleases }]
} = standardizeData({ data: [artistData], hasLoaded: unref(hasDataLoaded) }, formatArtistData)
Object.assign(state, {
artistID,
artistName,
artistPicture: artistPictureXL,
artistReleases
artistReleases,
currentTab: Object.keys(artistReleases)[0]
})
})
.catch(err => console.error(err))
// ? Is it not granted that it's always 'all' ?
state.currentTab = Object.keys(artistReleases)[0]
const sortedData = computed(() => {
if (!unref(hasDataLoaded)) {
return []
}
const reset = () => {
state.currentTab = ''
state.sortKey = 'releaseDate'
state.sortOrder = 'desc'
}
onDeactivated(reset)
onMounted(() => {
socket.on('show_artist', setupData)
})
const showTable = computed(() => {
if (Object.keys(state.artistReleases).length !== 0) {
let sortKey = state.sortKey
if (sortKey == 'releaseTracksNumber') {
if (sortKey === 'releaseTracksNumber') {
sortKey = o => new Number(o.releaseTracksNumber)
}
return orderBy(currentRelease.value, sortKey, state.sortOrder)
}
return []
return orderBy(state.currentRelease, sortKey, state.sortOrder)
})
const changeTab = newTab => {
state.currentTab = newTab
}
return {
...toRefs(state),
downloadLink: computed(() => `https://www.deezer.com/artist/${state.artistID}`),
downloadLink: computed(() => `https://www.deezer.com/artist/${unref(artistID)}`),
headerStyle: computed(() => ({
backgroundImage: `linear-gradient(to bottom, transparent 0%, var(--main-background) 100%), url(${state.artistPicture})`
})),
showTable,
sortedData,
sendAddToQueue,
currentRelease
checkNewRelease,
changeTab
}
},
data() {
@ -170,19 +171,8 @@ export default {
this.sortKey = key
this.sortOrder = 'asc'
}
},
changeTab(tab) {
this.currentTab = tab
},
checkNewRelease(date) {
let g1 = new Date()
let g2 = new Date(date)
g2.setDate(g2.getDate() + 3)
g1.setHours(0, 0, 0, 0)
return g1.getTime() <= g2.getTime()
}
}
}
})
</script>

View File

@ -7,7 +7,7 @@
}"
>
<h1 class="flex items-center m-0 text-5xl">
{{ title }} <i v-if="explicit" class="material-icons explicit-icon explicit-icon--right">explicit</i>
{{ title }} <i v-if="explicit" class="material-icons title-icon title-icon--right">explicit</i>
</h1>
<h2 class="m-0 mb-3 text-lg">
@ -60,7 +60,7 @@
</td>
<td class="table__cell--large table__cell--with-icon">
<div class="table__cell-content table__cell-content--vertical-center">
<i v-if="track.explicit_lyrics" class="material-icons explicit-icon"> explicit </i>
<i v-if="track.explicit_lyrics" class="material-icons title-icon"> explicit </i>
{{
track.title +
(track.title_version && track.title.indexOf(track.title_version) == -1
@ -127,7 +127,7 @@
</td>
<td>{{ i + 1 }}</td>
<td class="flex items-center">
<i v-if="track.explicit" class="material-icons explicit-icon">explicit</i>
<i v-if="track.explicit" class="material-icons title-icon">explicit</i>
{{ track.name }}
</td>
<td>{{ track.artists[0].name }}</td>

View File

@ -20,7 +20,7 @@
<span class="primary-text">
<i
v-if="release.isAlbumExplicit"
class="material-icons explicit-icon"
class="material-icons title-icon"
style="font-size: 1.0625rem !important"
>
explicit

View File

@ -36,7 +36,7 @@
<td class="table__cell table__cell--large">
<div class="break-words table__cell-content table__cell-content--vertical-center">
<i v-if="track.isTrackExplicit" class="material-icons explicit-icon">explicit</i>
<i v-if="track.isTrackExplicit" class="material-icons title-icon">explicit</i>
{{ formatTitle(track) }}
</div>
</td>

View File

@ -1,8 +1,8 @@
import { socket } from '@/utils/socket'
import { getPropertyWithFallback } from '@/utils/utils'
export function formatArtistData(artistData) {
return {
artistID: getPropertyWithFallback(artistData, 'id'),
artistName: getPropertyWithFallback(artistData, 'name'),
artistPictureXL: getPropertyWithFallback(artistData, 'picture_xl'),
artistReleases: formatArtistReleases(getPropertyWithFallback(artistData, 'releases'))
@ -33,3 +33,27 @@ function formatArtistReleases(artistReleases) {
return formattedReleases
}
let artistData = {}
let cached = false
export function getArtistData(artistID) {
if (cached) {
return artistData
} else {
socket.emit('getTracklist', {
type: 'artist',
id: artistID
})
return new Promise((resolve, reject) => {
socket.on('show_artist', data => {
artistData = data
// cached = true
socket.off('show_artist')
resolve(data)
})
})
}
}

View File

@ -35,7 +35,10 @@ const routes = [
{
path: '/artist/:id',
name: 'Artist',
component: Artist
component: Artist,
meta: {
notKeepAlive: true
}
},
{
path: '/album/:id',
@ -123,12 +126,6 @@ router.beforeEach((to, from, next) => {
let getTracklistParams = null
switch (to.name) {
case 'Artist':
getTracklistParams = {
type: 'artist',
id: to.params.id
}
break
case 'Tracklist':
getTracklistParams = {
type: to.params.type,

View File

@ -26,15 +26,22 @@
-webkit-font-smoothing: antialiased;
}
.material-icons.explicit-icon {
.material-icons.title-icon {
margin-right: 0.3125em;
margin-left: -3px;
}
.material-icons.title-icon.title-icon--right {
margin-right: 0px;
margin-left: 0.3125em;
}
.material-icons.title-icon.title-icon--explicit {
color: hsl(240, 5%, 59%);
}
.material-icons.explicit-icon.explicit-icon--right {
margin-right: 0px;
margin-left: 0.3125em;
.material-icons.title-icon.title-icon--new {
color: hsl(27, 100%, 50%);
}
.material-icons.disabled {

14
src/utils/dates.js Normal file
View File

@ -0,0 +1,14 @@
/**
* @param {Date} dateToCheck
* @returns {boolean} The passed date is less than 3 days distant from today,
* therefore it's considered a new release, if referring to a track or album
*/
export function checkNewRelease(dateToCheck) {
let now = new Date()
now.setHours(0, 0, 0, 0)
dateToCheck = new Date(dateToCheck)
dateToCheck.setDate(dateToCheck.getDate() + 3)
return now.getTime() <= dateToCheck.getTime()
}