From 5d35a3659e72f6830476737ad36ebfed818deb50 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Sat, 23 Dec 2017 21:37:11 +0100 Subject: [PATCH] Now use vuex to manage state for favorites --- front/src/components/audio/track/Table.vue | 2 +- front/src/components/favorites/List.vue | 10 +-- .../favorites/TrackFavoriteIcon.vue | 18 ++--- front/src/favorites/tracks.js | 57 -------------- front/src/store/auth.js | 10 ++- front/src/store/favorites.js | 78 +++++++++++++++++++ front/src/store/index.js | 2 + 7 files changed, 99 insertions(+), 78 deletions(-) delete mode 100644 front/src/favorites/tracks.js create mode 100644 front/src/store/favorites.js diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue index 49323186..8a591d3b 100644 --- a/front/src/components/audio/track/Table.vue +++ b/front/src/components/audio/track/Table.vue @@ -58,7 +58,7 @@ Keep your PRIVATE_TOKEN secret as it gives access to your account. </div> <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"> 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> diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 91efd729..aef4bea9 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -6,7 +6,7 @@ </div> <h2 v-if="results" class="ui center aligned icon header"> <i class="circular inverted heart pink icon"></i> - {{ favoriteTracks.count }} favorites + {{ $store.state.favorites.count }} favorites </h2> <radio-button type="favorites"></radio-button> </div> @@ -55,10 +55,8 @@ <script> import $ from 'jquery' -import Vue from 'vue' import logger from '@/logging' import config from '@/config' -import favoriteTracks from '@/favorites/tracks' import TrackTable from '@/components/audio/track/Table' import RadioButton from '@/components/radios/Button' import Pagination from '@/components/Pagination' @@ -80,7 +78,6 @@ export default { isLoading: false, nextLink: null, previousLink: null, - favoriteTracks, page: parseInt(this.defaultPage), paginateBy: parseInt(this.defaultPaginateBy || 25), orderingDirection: defaultOrdering.direction, @@ -122,10 +119,9 @@ export default { self.results = response.data self.nextLink = response.data.next self.previousLink = response.data.previous - Vue.set(favoriteTracks, 'count', response.data.count) - favoriteTracks.count = response.data.count + self.$store.commit('favorites/count', response.data.count) 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') self.isLoading = false diff --git a/front/src/components/favorites/TrackFavoriteIcon.vue b/front/src/components/favorites/TrackFavoriteIcon.vue index 5e3e5b07..5abc57a9 100644 --- a/front/src/components/favorites/TrackFavoriteIcon.vue +++ b/front/src/components/favorites/TrackFavoriteIcon.vue @@ -1,5 +1,5 @@ <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> <template v-if="isFavorite"> In favorites @@ -8,23 +8,23 @@ Add to favorites </template> </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> <script> -import favoriteTracks from '@/favorites/tracks' +import {mapState} from 'vuex' export default { props: { track: {type: Object}, button: {type: Boolean, default: false} }, - data () { - return { - favoriteTracks - } - }, computed: { + ...mapState({ + favorites: state => { + return state.favorites.tracks + } + }), title () { if (this.isFavorite) { return 'Remove from favorites' @@ -33,7 +33,7 @@ export default { } }, isFavorite () { - return favoriteTracks.objects[this.track.id] + return this.$store.getters['favorites/isFavorite'](this.track.id) } } diff --git a/front/src/favorites/tracks.js b/front/src/favorites/tracks.js deleted file mode 100644 index 45d05c50..00000000 --- a/front/src/favorites/tracks.js +++ /dev/null @@ -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) - } - }) - } - -} diff --git a/front/src/store/auth.js b/front/src/store/auth.js index 851d9c21..d4b23adc 100644 --- a/front/src/store/auth.js +++ b/front/src/store/auth.js @@ -34,6 +34,9 @@ export default { }, token: (state, value) => { state.token = value + }, + permission: (state, {key, status}) => { + state.availablePermissions[key] = status } }, actions: { @@ -77,17 +80,16 @@ export default { commit('authenticated', false) } }, - fetchProfile ({commit, state}) { + fetchProfile ({commit, dispatch, state}) { let resource = Vue.resource(USER_PROFILE_URL) return resource.get({}).then((response) => { logger.default.info('Successfully fetched user profile') let data = response.data commit('profile', data) - // favoriteTracks.fetch() - console.log('AFTER') + dispatch('favorites/fetch', null, {root: true}) Object.keys(data.permissions).forEach(function (key) { // 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 }, (response) => { diff --git a/front/src/store/favorites.js b/front/src/store/favorites.js new file mode 100644 index 00000000..8bb4bb5a --- /dev/null +++ b/front/src/store/favorites.js @@ -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) + } + }) + } + } +} diff --git a/front/src/store/index.js b/front/src/store/index.js index 35e50e03..99e466e5 100644 --- a/front/src/store/index.js +++ b/front/src/store/index.js @@ -1,6 +1,7 @@ import Vue from 'vue' import Vuex from 'vuex' +import favorites from './favorites' import auth from './auth' import queue from './queue' import radios from './radios' @@ -11,6 +12,7 @@ Vue.use(Vuex) export default new Vuex.Store({ modules: { auth, + favorites, queue, radios, player -- GitLab