Now use vuex to manage state for favorites

This commit is contained in:
Eliot Berriot 2017-12-23 21:37:11 +01:00
parent b5ce65fc3e
commit 5d35a3659e
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
7 changed files with 99 additions and 78 deletions

View File

@ -58,7 +58,7 @@
Keep your PRIVATE_TOKEN secret as it gives access to your account. Keep your PRIVATE_TOKEN secret as it gives access to your account.
</div> </div>
<pre> <pre>
export PRIVATE_TOKEN="{{ $store.state.auth.token ()}}" export PRIVATE_TOKEN="{{ $store.state.auth.token }}"
<template v-for="track in tracks"><template v-if="track.files.length > 0"> <template v-for="track in tracks"><template v-if="track.files.length > 0">
curl -G -o "{{ track.files[0].filename }}" <template v-if="$store.state.auth.authenticated">--header "Authorization: JWT $PRIVATE_TOKEN"</template> "{{ backend.absoluteUrl(track.files[0].path) }}"</template></template> curl -G -o "{{ track.files[0].filename }}" <template v-if="$store.state.auth.authenticated">--header "Authorization: JWT $PRIVATE_TOKEN"</template> "{{ backend.absoluteUrl(track.files[0].path) }}"</template></template>
</pre> </pre>

View File

@ -6,7 +6,7 @@
</div> </div>
<h2 v-if="results" class="ui center aligned icon header"> <h2 v-if="results" class="ui center aligned icon header">
<i class="circular inverted heart pink icon"></i> <i class="circular inverted heart pink icon"></i>
{{ favoriteTracks.count }} favorites {{ $store.state.favorites.count }} favorites
</h2> </h2>
<radio-button type="favorites"></radio-button> <radio-button type="favorites"></radio-button>
</div> </div>
@ -55,10 +55,8 @@
<script> <script>
import $ from 'jquery' import $ from 'jquery'
import Vue from 'vue'
import logger from '@/logging' import logger from '@/logging'
import config from '@/config' import config from '@/config'
import favoriteTracks from '@/favorites/tracks'
import TrackTable from '@/components/audio/track/Table' import TrackTable from '@/components/audio/track/Table'
import RadioButton from '@/components/radios/Button' import RadioButton from '@/components/radios/Button'
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
@ -80,7 +78,6 @@ export default {
isLoading: false, isLoading: false,
nextLink: null, nextLink: null,
previousLink: null, previousLink: null,
favoriteTracks,
page: parseInt(this.defaultPage), page: parseInt(this.defaultPage),
paginateBy: parseInt(this.defaultPaginateBy || 25), paginateBy: parseInt(this.defaultPaginateBy || 25),
orderingDirection: defaultOrdering.direction, orderingDirection: defaultOrdering.direction,
@ -122,10 +119,9 @@ export default {
self.results = response.data self.results = response.data
self.nextLink = response.data.next self.nextLink = response.data.next
self.previousLink = response.data.previous self.previousLink = response.data.previous
Vue.set(favoriteTracks, 'count', response.data.count) self.$store.commit('favorites/count', response.data.count)
favoriteTracks.count = response.data.count
self.results.results.forEach((track) => { self.results.results.forEach((track) => {
Vue.set(favoriteTracks.objects, track.id, true) self.$store.commit('favorites/track', {id: track.id, value: true})
}) })
logger.default.timeEnd('Loading user favorites') logger.default.timeEnd('Loading user favorites')
self.isLoading = false self.isLoading = false

View File

@ -1,5 +1,5 @@
<template> <template>
<button @click="favoriteTracks.set(track.id, !isFavorite)" v-if="button" :class="['ui', 'pink', {'inverted': isFavorite}, {'favorited': isFavorite}, 'button']"> <button @click="$store.dispatch('favorites/set', {id: track.id, value: !isFavorite})" v-if="button" :class="['ui', 'pink', {'inverted': isFavorite}, {'favorited': isFavorite}, 'button']">
<i class="heart icon"></i> <i class="heart icon"></i>
<template v-if="isFavorite"> <template v-if="isFavorite">
In favorites In favorites
@ -8,23 +8,23 @@
Add to favorites Add to favorites
</template> </template>
</button> </button>
<i v-else @click="favoriteTracks.set(track.id, !isFavorite)" :class="['favorite-icon', 'heart', {'pink': isFavorite}, {'favorited': isFavorite}, 'link', 'icon']" :title="title"></i> <i v-else @click="$store.dispatch('favorites/set', {id: track.id, value: !isFavorite})" :class="['favorite-icon', 'heart', {'pink': isFavorite}, {'favorited': isFavorite}, 'link', 'icon']" :title="title"></i>
</template> </template>
<script> <script>
import favoriteTracks from '@/favorites/tracks' import {mapState} from 'vuex'
export default { export default {
props: { props: {
track: {type: Object}, track: {type: Object},
button: {type: Boolean, default: false} button: {type: Boolean, default: false}
}, },
data () {
return {
favoriteTracks
}
},
computed: { computed: {
...mapState({
favorites: state => {
return state.favorites.tracks
}
}),
title () { title () {
if (this.isFavorite) { if (this.isFavorite) {
return 'Remove from favorites' return 'Remove from favorites'
@ -33,7 +33,7 @@ export default {
} }
}, },
isFavorite () { isFavorite () {
return favoriteTracks.objects[this.track.id] return this.$store.getters['favorites/isFavorite'](this.track.id)
} }
} }

View File

@ -1,57 +0,0 @@
import config from '@/config'
import logger from '@/logging'
import Vue from 'vue'
const REMOVE_URL = config.API_URL + 'favorites/tracks/remove/'
const FAVORITES_URL = config.API_URL + 'favorites/tracks/'
export default {
objects: {},
count: 0,
set (id, newValue) {
let self = this
Vue.set(self.objects, id, newValue)
if (newValue) {
Vue.set(self, 'count', self.count + 1)
let resource = Vue.resource(FAVORITES_URL)
resource.save({}, {'track': id}).then((response) => {
logger.default.info('Successfully added track to favorites')
}, (response) => {
logger.default.info('Error while adding track to favorites')
Vue.set(self.objects, id, !newValue)
Vue.set(self, 'count', self.count - 1)
})
} else {
Vue.set(self, 'count', self.count - 1)
let resource = Vue.resource(REMOVE_URL)
resource.delete({}, {'track': id}).then((response) => {
logger.default.info('Successfully removed track from favorites')
}, (response) => {
logger.default.info('Error while removing track from favorites')
Vue.set(self.objects, id, !newValue)
Vue.set(self, 'count', self.count + 1)
})
}
},
toggle (id) {
let isFavorite = this.objects[id]
this.set(id, !isFavorite)
},
fetch (url) {
// will fetch favorites by batches from API to have them locally
var self = this
url = url || FAVORITES_URL
let resource = Vue.resource(url)
resource.get().then((response) => {
logger.default.info('Fetched a batch of ' + response.data.results.length + ' favorites')
Vue.set(self, 'count', response.data.count)
response.data.results.forEach(result => {
Vue.set(self.objects, result.track, true)
})
if (response.data.next) {
self.fetch(response.data.next)
}
})
}
}

View File

@ -34,6 +34,9 @@ export default {
}, },
token: (state, value) => { token: (state, value) => {
state.token = value state.token = value
},
permission: (state, {key, status}) => {
state.availablePermissions[key] = status
} }
}, },
actions: { actions: {
@ -77,17 +80,16 @@ export default {
commit('authenticated', false) commit('authenticated', false)
} }
}, },
fetchProfile ({commit, state}) { fetchProfile ({commit, dispatch, state}) {
let resource = Vue.resource(USER_PROFILE_URL) let resource = Vue.resource(USER_PROFILE_URL)
return resource.get({}).then((response) => { return resource.get({}).then((response) => {
logger.default.info('Successfully fetched user profile') logger.default.info('Successfully fetched user profile')
let data = response.data let data = response.data
commit('profile', data) commit('profile', data)
// favoriteTracks.fetch() dispatch('favorites/fetch', null, {root: true})
console.log('AFTER')
Object.keys(data.permissions).forEach(function (key) { Object.keys(data.permissions).forEach(function (key) {
// this makes it easier to check for permissions in templates // this makes it easier to check for permissions in templates
state.availablePermissions[key] = data.permissions[String(key)].status commit('permission', {key, status: data.permissions[String(key)].status})
}) })
return response.data return response.data
}, (response) => { }, (response) => {

View File

@ -0,0 +1,78 @@
import Vue from 'vue'
import config from '@/config'
import logger from '@/logging'
const REMOVE_URL = config.API_URL + 'favorites/tracks/remove/'
const FAVORITES_URL = config.API_URL + 'favorites/tracks/'
export default {
namespaced: true,
state: {
tracks: [],
count: 0
},
mutations: {
track: (state, {id, value}) => {
if (value) {
state.tracks.push(id)
} else {
let i = state.tracks.indexOf(id)
if (i > -1) {
state.tracks.splice(i, 1)
}
}
},
count: (state, value) => {
state.count = value
}
},
getters: {
isFavorite: (state) => (id) => {
return state.tracks.indexOf(id) > -1
}
},
actions: {
set ({commit, state}, {id, value}) {
commit('track', {id, value})
if (value) {
commit('count', state.count + 1)
let resource = Vue.resource(FAVORITES_URL)
resource.save({}, {'track': id}).then((response) => {
logger.default.info('Successfully added track to favorites')
}, (response) => {
logger.default.info('Error while adding track to favorites')
commit('track', {id, value: !value})
commit('count', state.count - 1)
})
} else {
commit('count', state.count - 1)
let resource = Vue.resource(REMOVE_URL)
resource.delete({}, {'track': id}).then((response) => {
logger.default.info('Successfully removed track from favorites')
}, (response) => {
logger.default.info('Error while removing track from favorites')
commit('track', {id, value: !value})
commit('count', state.count + 1)
})
}
},
toggle ({getters, dispatch}, id) {
dispatch('set', {id, value: getters['isFavorite'](id)})
},
fetch ({dispatch, state, commit}, url) {
// will fetch favorites by batches from API to have them locally
url = url || FAVORITES_URL
let resource = Vue.resource(url)
resource.get().then((response) => {
logger.default.info('Fetched a batch of ' + response.data.results.length + ' favorites')
response.data.results.forEach(result => {
commit('track', {id: result.track, value: true})
})
commit('count', state.tracks.length)
if (response.data.next) {
dispatch('fetch', response.data.next)
}
})
}
}
}

View File

@ -1,6 +1,7 @@
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import favorites from './favorites'
import auth from './auth' import auth from './auth'
import queue from './queue' import queue from './queue'
import radios from './radios' import radios from './radios'
@ -11,6 +12,7 @@ Vue.use(Vuex)
export default new Vuex.Store({ export default new Vuex.Store({
modules: { modules: {
auth, auth,
favorites,
queue, queue,
radios, radios,
player player