mirror of
https://github.com/koel/koel
synced 2024-11-24 05:03:05 +00:00
Adding Vuex
This commit is contained in:
parent
024caa40e1
commit
0ad2916d1d
24 changed files with 1466 additions and 159 deletions
|
@ -14,7 +14,10 @@
|
|||
"url": "https://github.com/phanan/koel"
|
||||
},
|
||||
"babel": {
|
||||
"presets": ["es2015"]
|
||||
"presets": [
|
||||
"es2015",
|
||||
"stage-0"
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "vue",
|
||||
|
@ -44,6 +47,7 @@
|
|||
"autoprefixer": "^6.7.2",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-stage-0": "^6.22.0",
|
||||
"babel-register": "^6.23.0",
|
||||
"babel-runtime": "^6.22.0",
|
||||
"chai": "^3.4.1",
|
||||
|
@ -57,7 +61,8 @@
|
|||
"laravel-mix": "^0.8.0",
|
||||
"mocha": "^2.3.4",
|
||||
"node-sass": "^3.4.2",
|
||||
"sinon": "^1.17.2"
|
||||
"sinon": "^1.17.2",
|
||||
"vuex": "^2.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "yarn build",
|
||||
|
|
|
@ -2,6 +2,8 @@ import './static-loader'
|
|||
import Vue from 'vue'
|
||||
import { event } from './utils'
|
||||
import { http } from './services'
|
||||
import store from './store'
|
||||
import App from './app.vue'
|
||||
import { VirtualScroller } from 'vue-virtual-scroller/dist/vue-virtual-scroller'
|
||||
Vue.component('virtual-scroller', VirtualScroller)
|
||||
|
||||
|
@ -13,7 +15,8 @@ Vue.component('virtual-scroller', VirtualScroller)
|
|||
*/
|
||||
new Vue({
|
||||
el: '#app',
|
||||
render: h => h(require('./app.vue')),
|
||||
store,
|
||||
render: h => h(App),
|
||||
created () {
|
||||
event.init()
|
||||
http.init()
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
|
||||
import siteHeader from './components/site-header/index.vue'
|
||||
import siteFooter from './components/site-footer/index.vue'
|
||||
|
@ -47,13 +48,26 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
// The app has just been initialized, check if we can get the user data with an already existing token
|
||||
const token = ls.get('jwt-token')
|
||||
if (token) {
|
||||
this.authenticated = true
|
||||
computed: {
|
||||
...mapGetters(['jwtToken'])
|
||||
},
|
||||
|
||||
watch: {
|
||||
jwtToken (token) {
|
||||
if (!token) {
|
||||
// log out
|
||||
this.authenticated = false
|
||||
forceReloadWindow()
|
||||
return
|
||||
}
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
console.log(this.$store._modules)
|
||||
// if a jwt token is found in local storage, init
|
||||
this.jwtToken && this.init()
|
||||
|
||||
// Create the element to be the ghost drag image.
|
||||
const dragGhost = document.createElement('div')
|
||||
|
@ -73,29 +87,37 @@ export default {
|
|||
methods: {
|
||||
init () {
|
||||
showOverlay()
|
||||
this.authenticated = true
|
||||
|
||||
// Make the most important HTTP request to get all necessary data from the server.
|
||||
// Afterwards, init all mandatory stores and services.
|
||||
sharedStore.init().then(() => {
|
||||
playback.init()
|
||||
hideOverlay()
|
||||
this.$store.dispatch('initGlobal').then(data => {
|
||||
this.$store.dispatch('initArtists', data)
|
||||
.then(artists => this.$store.dispatch('initAlbums', artists))
|
||||
.then(albums => this.$store.dispatch('initSongs', albums))
|
||||
.then(() => this.$store.dispatch('initInteractions', data))
|
||||
.then(() => this.$store.dispatch('initPlaylists', data))
|
||||
.then(() => this.$store.dispatch('initSettings', data))
|
||||
.then(() => this.$store.dispatch('initUsers', data))
|
||||
.then(() => this.$store.dispatch('initPreferences', data))
|
||||
.then(() => playback.init())
|
||||
.then(({ player: { media } }) => {
|
||||
event.emit('equalizer:init', media)
|
||||
hideOverlay()
|
||||
// Ask for user's notification permission.
|
||||
this.requestNotifPermission()
|
||||
|
||||
// Ask for user's notification permission.
|
||||
this.requestNotifPermission()
|
||||
// To confirm or not to confirm closing, it's a question.
|
||||
window.onbeforeunload = e => {
|
||||
if (!preferences.confirmClosing) {
|
||||
return
|
||||
}
|
||||
|
||||
// To confirm or not to confirm closing, it's a question.
|
||||
window.onbeforeunload = e => {
|
||||
if (!preferences.confirmClosing) {
|
||||
return
|
||||
}
|
||||
|
||||
// Notice that a custom message like this has ceased to be supported
|
||||
// starting from Chrome 51.
|
||||
return 'You asked Koel to confirm before closing, so here it is.'
|
||||
}
|
||||
|
||||
// Let all other components know we're ready.
|
||||
event.emit('koel:ready')
|
||||
// Notice that a custom message like this has ceased to be supported
|
||||
// starting from Chrome 51.
|
||||
return 'You asked Koel to confirm before closing, so here it is.'
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
this.authenticated = false
|
||||
})
|
||||
|
@ -193,16 +215,6 @@ export default {
|
|||
*/
|
||||
'songs:edit': songs => this.$refs.editSongsForm.open(songs),
|
||||
|
||||
/**
|
||||
* Log the current user out and reset the application state.
|
||||
*/
|
||||
logout () {
|
||||
userStore.logout().then((r) => {
|
||||
ls.remove('jwt-token')
|
||||
forceReloadWindow()
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Init our basic, custom router on ready to determine app state.
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<form @submit.prevent="login" :class="{ error: failed }">
|
||||
<input v-model="email" type="email" placeholder="Email Address" autofocus required>
|
||||
<input v-model="password" type="password" placeholder="Password" required>
|
||||
<input v-model="credentials.email" type="email" placeholder="Email Address" autofocus required>
|
||||
<input v-model="credentials.password" type="password" placeholder="Password" required>
|
||||
<button type="submit">Log In</button>
|
||||
</form>
|
||||
</template>
|
||||
|
@ -13,8 +13,10 @@ import { event } from '../../utils'
|
|||
export default {
|
||||
data () {
|
||||
return {
|
||||
email: '',
|
||||
password: '',
|
||||
credentials: {
|
||||
email: '',
|
||||
password: ''
|
||||
},
|
||||
failed: false
|
||||
}
|
||||
},
|
||||
|
@ -22,14 +24,11 @@ export default {
|
|||
methods: {
|
||||
login () {
|
||||
this.failed = false
|
||||
|
||||
userStore.login(this.email, this.password).then(() => {
|
||||
this.$store.dispatch('login', this.credentials).then(() => {
|
||||
this.failed = false
|
||||
|
||||
// Reset the password so that the next login will have this field empty.
|
||||
this.password = ''
|
||||
|
||||
event.emit('user:loggedin')
|
||||
this.credentials.password = ''
|
||||
}).catch(() => {
|
||||
this.failed = true
|
||||
})
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
import { map, cloneDeep, each } from 'lodash'
|
||||
import nouislider from 'nouislider'
|
||||
|
||||
import { mapGetters } from 'vuex'
|
||||
import { isAudioContextSupported, event, $ } from '../../utils'
|
||||
import { equalizerStore, preferenceStore as preferences } from '../../stores'
|
||||
|
||||
|
@ -44,6 +45,7 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['equalizerSettings', 'preferenceByKey']),
|
||||
presets () {
|
||||
const clonedPreset = cloneDeep(equalizerStore.presets)
|
||||
// Prepend an empty option for instruction purpose.
|
||||
|
@ -69,7 +71,13 @@ export default {
|
|||
if (~~val !== -1) {
|
||||
this.loadPreset(equalizerStore.getPresetById(val))
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
created () {
|
||||
event.on('equalizer:init', mediaElement => {
|
||||
isAudioContextSupported() && this.init(mediaElement)
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -78,8 +86,6 @@ export default {
|
|||
* @param {Element} player The audio player's node.
|
||||
*/
|
||||
init (player) {
|
||||
const settings = equalizerStore.get()
|
||||
|
||||
const AudioContext = window.AudioContext ||
|
||||
window.webkitAudioContext ||
|
||||
window.mozAudioContext ||
|
||||
|
@ -89,7 +95,7 @@ export default {
|
|||
const context = new AudioContext()
|
||||
|
||||
this.preampGainNode = context.createGain()
|
||||
this.changePreampGain(settings.preamp)
|
||||
this.changePreampGain(this.equalizerSettings.preamp)
|
||||
|
||||
const source = context.createMediaElementSource(player)
|
||||
source.connect(this.preampGainNode)
|
||||
|
@ -109,7 +115,7 @@ export default {
|
|||
filter.type = 'peaking'
|
||||
}
|
||||
|
||||
filter.gain.value = settings.gains[i] ? settings.gains[i] : 0
|
||||
filter.gain.value = this.equalizerSettings.gains[i] ? this.equalizerSettings.gains[i] : 0
|
||||
filter.Q.value = 1
|
||||
filter.frequency.value = frequency
|
||||
|
||||
|
@ -131,12 +137,11 @@ export default {
|
|||
* Create the UI sliders for both the preamp and the normal bands.
|
||||
*/
|
||||
createSliders () {
|
||||
const config = equalizerStore.get()
|
||||
each(Array.from(document.querySelectorAll('#equalizer .slider')), (el, i) => {
|
||||
nouislider.create(el, {
|
||||
connect: [false, true],
|
||||
// the first element is the preamp. The rest are gains.
|
||||
start: i === 0 ? config.preamp : config.gains[i - 1],
|
||||
start: i === 0 ? this.equalizerSettings.preamp : this.equalizerSettings.gains[i - 1],
|
||||
range: { min: -20, max: 20 },
|
||||
orientation: 'vertical',
|
||||
direction: 'rtl'
|
||||
|
@ -165,7 +170,7 @@ export default {
|
|||
})
|
||||
|
||||
// Now we set this value to trigger the audio processing.
|
||||
this.selectedPresetIndex = preferences.selectedPreset
|
||||
this.selectedPresetIndex = this.preferenceByKey('selectedPreset')
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -215,12 +220,6 @@ export default {
|
|||
equalizerStore.set(this.preampGainValue, map(this.bands, 'filter.gain.value'))
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
event.on('equalizer:init', player => {
|
||||
isAudioContextSupported() && this.init(player)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<span class="profile" id="userBadge">
|
||||
<a class="view-profile control" href="/#!/profile">
|
||||
<img class="avatar" :src="state.current.avatar" alt="Avatar"/>
|
||||
<span class="name">{{ state.current.name }}</span>
|
||||
<img class="avatar" :src="currentUser.avatar" alt="Avatar"/>
|
||||
<span class="name">{{ currentUser.name }}</span>
|
||||
</a>
|
||||
|
||||
<a class="logout" @click.prevent="logout"><i class="fa fa-sign-out control"></i></a>
|
||||
|
@ -10,22 +10,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { userStore } from '../../stores'
|
||||
import { event } from '../../utils'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'site-header--user-badge',
|
||||
|
||||
data () {
|
||||
return {
|
||||
state: userStore.state
|
||||
}
|
||||
computed: {
|
||||
...mapGetters(['currentUser'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
logout () {
|
||||
event.emit('logout')
|
||||
}
|
||||
...mapActions(['logout'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -18,80 +18,81 @@ export const playback = {
|
|||
* Initialize the playback service for this whole Koel app.
|
||||
*/
|
||||
init () {
|
||||
// We don't need to init this service twice, or the media events will be duplicated.
|
||||
if (this.initialized) {
|
||||
return
|
||||
}
|
||||
|
||||
this.player = plyr.setup({
|
||||
controls: []
|
||||
})[0]
|
||||
|
||||
this.audio = document.querySelector('audio')
|
||||
this.volumeInput = document.getElementById('volumeRange')
|
||||
|
||||
/**
|
||||
* Listen to 'error' event on the audio player and play the next song if any.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('error', () => this.playNext(), true)
|
||||
|
||||
/**
|
||||
* Listen to 'ended' event on the audio player and play the next song in the queue.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('ended', e => {
|
||||
if (sharedStore.state.useLastfm && userStore.current.preferences.lastfm_session_key) {
|
||||
songStore.scrobble(queueStore.current)
|
||||
return new Promise(resolve => {
|
||||
// We don't need to init this service twice, or the media events will be duplicated.
|
||||
if (this.initialized) {
|
||||
return resolve()
|
||||
}
|
||||
|
||||
if (preferences.repeatMode === 'REPEAT_ONE') {
|
||||
this.restart()
|
||||
return
|
||||
this.player = plyr.setup({
|
||||
controls: []
|
||||
})[0]
|
||||
|
||||
this.audio = document.querySelector('audio')
|
||||
this.volumeInput = document.getElementById('volumeRange')
|
||||
|
||||
/**
|
||||
* Listen to 'error' event on the audio player and play the next song if any.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('error', () => this.playNext(), true)
|
||||
|
||||
/**
|
||||
* Listen to 'ended' event on the audio player and play the next song in the queue.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('ended', e => {
|
||||
if (sharedStore.state.useLastfm && userStore.current.preferences.lastfm_session_key) {
|
||||
songStore.scrobble(queueStore.current)
|
||||
}
|
||||
|
||||
if (preferences.repeatMode === 'REPEAT_ONE') {
|
||||
this.restart()
|
||||
return
|
||||
}
|
||||
|
||||
this.playNext()
|
||||
})
|
||||
|
||||
/**
|
||||
* Attempt to preload the next song.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('canplaythrough', e => {
|
||||
const nextSong = queueStore.next
|
||||
if (!nextSong || nextSong.preloaded || (isMobile.any && preferences.transcodeOnMobile)) {
|
||||
// Don't preload if
|
||||
// - there's no next song
|
||||
// - next song has already been preloaded
|
||||
// - we're on mobile and "transcode" option is checked
|
||||
return
|
||||
}
|
||||
|
||||
const audio = document.createElement('audio')
|
||||
audio.setAttribute('src', songStore.getSourceUrl(nextSong))
|
||||
audio.setAttribute('preload', 'auto')
|
||||
audio.load()
|
||||
nextSong.preloaded = true
|
||||
})
|
||||
|
||||
/**
|
||||
* Listen to 'input' event on the volume range control.
|
||||
* When user drags the volume control, this event will be triggered, and we
|
||||
* update the volume on the plyr object.
|
||||
*/
|
||||
this.volumeInput.addEventListener('input', e => this.setVolume(e.target.value))
|
||||
|
||||
// On init, set the volume to the value found in the local storage.
|
||||
this.setVolume(preferences.volume)
|
||||
|
||||
if ('mediaSession' in navigator) {
|
||||
navigator.mediaSession.setActionHandler('play', () => this.resume())
|
||||
navigator.mediaSession.setActionHandler('pause', () => this.pause())
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => this.playPrev())
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => this.playNext())
|
||||
}
|
||||
|
||||
this.playNext()
|
||||
this.initialized = true
|
||||
|
||||
resolve(this)
|
||||
})
|
||||
|
||||
/**
|
||||
* Attempt to preload the next song.
|
||||
*/
|
||||
document.querySelector('.plyr').addEventListener('canplaythrough', e => {
|
||||
const nextSong = queueStore.next
|
||||
if (!nextSong || nextSong.preloaded || (isMobile.any && preferences.transcodeOnMobile)) {
|
||||
// Don't preload if
|
||||
// - there's no next song
|
||||
// - next song has already been preloaded
|
||||
// - we're on mobile and "transcode" option is checked
|
||||
return
|
||||
}
|
||||
|
||||
const audio = document.createElement('audio')
|
||||
audio.setAttribute('src', songStore.getSourceUrl(nextSong))
|
||||
audio.setAttribute('preload', 'auto')
|
||||
audio.load()
|
||||
nextSong.preloaded = true
|
||||
})
|
||||
|
||||
/**
|
||||
* Listen to 'input' event on the volume range control.
|
||||
* When user drags the volume control, this event will be triggered, and we
|
||||
* update the volume on the plyr object.
|
||||
*/
|
||||
this.volumeInput.addEventListener('input', e => this.setVolume(e.target.value))
|
||||
|
||||
// On init, set the volume to the value found in the local storage.
|
||||
this.setVolume(preferences.volume)
|
||||
|
||||
// Init the equalizer if supported.
|
||||
event.emit('equalizer:init', this.player.media)
|
||||
|
||||
if ('mediaSession' in navigator) {
|
||||
navigator.mediaSession.setActionHandler('play', () => this.resume())
|
||||
navigator.mediaSession.setActionHandler('pause', () => this.pause())
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => this.playPrev())
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => this.playNext())
|
||||
}
|
||||
|
||||
this.initialized = true
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
29
resources/assets/js/store/actions.js
Normal file
29
resources/assets/js/store/actions.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { assign } from 'lodash'
|
||||
import isMobile from 'ismobilejs'
|
||||
|
||||
import { http } from '../services'
|
||||
import * as types from './mutation-types'
|
||||
|
||||
const actions = {
|
||||
initGlobal ({ commit }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
http.get('data', ({ data }) => {
|
||||
// Don't allow downloading on mobile devices
|
||||
data.allowDownload = data.allowDownload && !isMobile.any
|
||||
// Disable YouTube integration on mobile
|
||||
data.useYouTube = data.useYouTube && !isMobile.phone
|
||||
// If this is a new user, initialize his preferences as an empty object
|
||||
if (!data.currentUser.preferences) {
|
||||
data.currentUser.preferences = {}
|
||||
}
|
||||
// Keep a copy of the media path. We'll need this to properly warn the user later.
|
||||
data.originalMediaPath = data.settings.media_path
|
||||
commit(types.GLOBAL_INIT_DATA, data)
|
||||
|
||||
resolve(data)
|
||||
}, error => reject(error))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default actions
|
5
resources/assets/js/store/getters.js
Normal file
5
resources/assets/js/store/getters.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
const getters = {
|
||||
|
||||
}
|
||||
|
||||
export default getters
|
40
resources/assets/js/store/index.js
Normal file
40
resources/assets/js/store/index.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import state from './state'
|
||||
import actions from './actions'
|
||||
import getters from './getters'
|
||||
import mutations from './mutations'
|
||||
import albums from './modules/albums'
|
||||
import artists from './modules/artists'
|
||||
import equalizer from './modules/equalizer'
|
||||
import favorites from './modules/favorites'
|
||||
import playlists from './modules/playlists'
|
||||
import preferences from './modules/preferences'
|
||||
import queue from './modules/queue'
|
||||
import settings from './modules/settings'
|
||||
import songs from './modules/songs'
|
||||
import users from './modules/users'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production'
|
||||
|
||||
export default new Vuex.Store({
|
||||
state,
|
||||
actions,
|
||||
getters,
|
||||
mutations,
|
||||
modules: {
|
||||
albums,
|
||||
artists,
|
||||
equalizer,
|
||||
favorites,
|
||||
playlists,
|
||||
preferences,
|
||||
queue,
|
||||
settings,
|
||||
songs,
|
||||
users
|
||||
},
|
||||
strict: debug
|
||||
})
|
100
resources/assets/js/store/modules/albums.js
Normal file
100
resources/assets/js/store/modules/albums.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*eslint camelcase: ["error", {properties: "never"}]*/
|
||||
|
||||
import Vue from 'vue'
|
||||
import { reduce, each, union, difference, take, filter, orderBy } from 'lodash'
|
||||
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const cache = []
|
||||
|
||||
const state = {
|
||||
albums: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allAlbums: state => state.albums,
|
||||
albumById: state => id => cache[id],
|
||||
isEmptyAlbum: state => album => !album.songs.length,
|
||||
|
||||
getAlbumLength: state => album => {
|
||||
Vue.set(album, 'length', reduce(album.songs, (length, song) => length + song.length, 0))
|
||||
Vue.set(album, 'fmtLength', secondsToHis(album.length))
|
||||
return album.fmtLength
|
||||
},
|
||||
|
||||
mostPlayedAlbums: state => (n = 6) => {
|
||||
// Only non-unknown albums with actually play count are applicable.
|
||||
const applicable = filter(state.albums, album => album.playCount && album.id !== 1)
|
||||
return take(orderBy(applicable, 'playCount', 'desc'), n)
|
||||
},
|
||||
|
||||
recentlyAddedAlbums: state => (n = 6) => {
|
||||
const applicable = filter(state.albums, album => album.id !== 1)
|
||||
return take(orderBy(applicable, 'created_at', 'desc'), n)
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initAlbums ({ dispatch, commit, state }, artists) {
|
||||
return new Promise(resolve => {
|
||||
// Traverse through the artists array and add their albums into our master album list.
|
||||
const albums = reduce(artists, (albums, artist) => {
|
||||
// While we're doing so, for each album, we get its length
|
||||
// and keep a back reference to the artist too.
|
||||
each(artist.albums, album => dispatch('setupAlbum', { album, artist }))
|
||||
return albums.concat(artist.albums)
|
||||
}, [])
|
||||
|
||||
commit(types.ALBUM_INIT_STORE, albums)
|
||||
resolve(state.albums)
|
||||
})
|
||||
},
|
||||
|
||||
setupAlbum ({ commit }, { album, artist }) {
|
||||
return new Promise(resolve => {
|
||||
album.playCount = 0
|
||||
album.artist = artist
|
||||
album.info = null
|
||||
cache[album.id] = album
|
||||
|
||||
resolve(album)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.ALBUM_INIT_STORE] (state, albums) {
|
||||
state.albums = albums
|
||||
},
|
||||
|
||||
[types.ALBUM_SETUP] (state, { album, artist }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ALBUM_ADD] (state, { album }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ALBUM_ADD_SONGS_INTO_ALBUM] (state, { album, songs }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ALBUM_REMOVE_SONGS_FROM_ALBUM] (state, { album, songs }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ALBUM_REMOVE] (state, { albums }) {
|
||||
|
||||
},
|
||||
|
||||
[types.SET_INTERACTION_DATA] (state, { song: { album }, playCount }) {
|
||||
album.playCount += playCount
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
123
resources/assets/js/store/modules/artists.js
Normal file
123
resources/assets/js/store/modules/artists.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*eslint camelcase: ["error", {properties: "never"}]*/
|
||||
|
||||
import Vue from 'vue'
|
||||
import { reduce, each, clone, union, difference, take, filter, orderBy } from 'lodash'
|
||||
|
||||
import config from '../../config'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const UNKNOWN_ARTIST_ID = 1
|
||||
const VARIOUS_ARTISTS_ID = 2
|
||||
const cache = []
|
||||
|
||||
const state = {
|
||||
artists: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allArtists: state => state.artists,
|
||||
artistById: state => id => cache[id],
|
||||
isEmptyArtist: state => artist => !artist.albums.length,
|
||||
isVariousArtist: state => artist => artist.id === VARIOUS_ARTISTS_ID,
|
||||
isUnknownArtist: state => artist => artist.id === UNKNOWN_ARTIST_ID,
|
||||
songsByArtist: state => artist => artist.songs,
|
||||
artistImage: state => artist => {
|
||||
|
||||
},
|
||||
mostPlayedArtists: state => (n = 6) => {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initArtists ({ dispatch, commit, state }, { artists }) {
|
||||
return new Promise(resolve => {
|
||||
each(artists, artist => dispatch('setupArtist', artist))
|
||||
|
||||
commit(types.ARTIST_INIT_STORE, artists)
|
||||
resolve(state.artists)
|
||||
})
|
||||
},
|
||||
|
||||
setupArtist ({ commit }, artist) {
|
||||
return new Promise(resolve => {
|
||||
artist.playCount = 0
|
||||
if (!artist.image) {
|
||||
// Try to get an image from one of the albums.
|
||||
artist.image = config.unknownCover
|
||||
|
||||
artist.albums.every(album => {
|
||||
// If there's a "real" cover, use it.
|
||||
if (album.image !== config.unknownCover) {
|
||||
artist.image = album.cover
|
||||
|
||||
// I want to break free.
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Here we build a list of songs performed by the artist, so that we don't need to traverse
|
||||
// down the "artist > albums > items" route later.
|
||||
// This also makes sure songs in compilation albums are counted as well.
|
||||
artist.songs = reduce(artist.albums, (songs, album) => {
|
||||
// If the album is compilation, we cater for the songs contributed by this artist only.
|
||||
if (album.is_compilation) {
|
||||
return songs.concat(filter(album.songs, { contributing_artist_id: artist.id }))
|
||||
}
|
||||
|
||||
// Otherwise, just use all songs in the album.
|
||||
return songs.concat(album.songs)
|
||||
}, [])
|
||||
|
||||
artist.songCount = artist.songs.length
|
||||
artist.info = null
|
||||
cache[artist.id] = artist
|
||||
|
||||
resolve(artist)
|
||||
})
|
||||
},
|
||||
|
||||
addAlbumsIntoArtist ({ commit }, { artist, albums }) {
|
||||
commit(types.ARTIST_ADD_ALBUMS_INTO_ARTIST, { artist, albums })
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.ARTIST_INIT_STORE] (state, artists) {
|
||||
state.artists = artists
|
||||
},
|
||||
|
||||
[types.ARTIST_ADD] (state, { artists }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ARTIST_REMOVE] (state, { artists }) {
|
||||
|
||||
},
|
||||
|
||||
[types.ARTIST_ADD_ALBUMS_INTO_ARTIST] (state, { artist, albums }) {
|
||||
each(albums, album => {
|
||||
album.artist_id = artist.id
|
||||
album.artist = artist
|
||||
artist.playCount += album.playCount
|
||||
})
|
||||
|
||||
artist.albums = union(artist.albums, [].concat(albums))
|
||||
},
|
||||
|
||||
[types.ARTIST_REMOVE_ALBUMS_FROM_ARTIST] (state, { artist, albums }) {
|
||||
|
||||
},
|
||||
|
||||
[types.SET_INTERACTION_DATA] (state, { song: { artist }, playCount }) {
|
||||
artist.playCount += playCount
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
119
resources/assets/js/store/modules/equalizer.js
Normal file
119
resources/assets/js/store/modules/equalizer.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
import { find } from 'lodash'
|
||||
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
presets: [
|
||||
{
|
||||
id: 0,
|
||||
name: 'Default',
|
||||
preamp: 0,
|
||||
gains: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'Classical',
|
||||
preamp: -1,
|
||||
gains: [-1, -1, -1, -1, -1, -1, -7, -7, -7, -9]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Club',
|
||||
preamp: -6.7,
|
||||
gains: [-1, -1, 8, 5, 5, 5, 3, -1, -1, -1]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Dance',
|
||||
preamp: -4.3,
|
||||
gains: [9, 7, 2, -1, -1, -5, -7, -7, -1, -1]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Full Bass',
|
||||
preamp: -7.2,
|
||||
gains: [-8, 9, 9, 5, 1, -4, -8, -10, -11, -11]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Full Treble',
|
||||
preamp: -12,
|
||||
gains: [-9, -9, -9, -4, 2, 11, 16, 16, 16, 16]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Headphone',
|
||||
preamp: -8,
|
||||
gains: [4, 11, 5, -3, -2, 1, 4, 9, 12, 14]
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Large Hall',
|
||||
preamp: -7.2,
|
||||
gains: [10, 10, 5, 5, -1, -4, -4, -4, -1, -1]
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Live',
|
||||
preamp: -5.3,
|
||||
gains: [-4, -1, 4, 5, 5, 5, 4, 2, 2, 2]
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Pop',
|
||||
preamp: -6.2,
|
||||
gains: [-1, 4, 7, 8, 5, -1, -2, -2, -1, -1]
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Reggae',
|
||||
preamp: -8.2,
|
||||
gains: [-1, -1, -1, -5, -1, 6, 6, -1, -1, -1]
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Rock',
|
||||
preamp: -10,
|
||||
gains: [8, 4, -5, -8, -3, 4, 8, 11, 11, 11]
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: 'Soft Rock',
|
||||
preamp: -5.3,
|
||||
gains: [4, 4, 2, -1, -4, -5, -3, -1, 2, 8]
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: 'Techno',
|
||||
preamp: -7.7,
|
||||
gains: [8, 5, -1, -5, -4, -1, 8, 9, 9, 8]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const getters = {
|
||||
presetById: state => id => find(state.presets, { id }),
|
||||
equalizerSettings: (state, getters) => {
|
||||
const savedPresetId = getters.preferenceByKey('selectedPreset')
|
||||
if (!savedPresetId) {
|
||||
return getters.presetById(savedPresetId)
|
||||
}
|
||||
return getters.preferenceByKey('equalizer')
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.EQUALIZER_SAVE] (state, { preamp, gains }) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
61
resources/assets/js/store/modules/favorites.js
Normal file
61
resources/assets/js/store/modules/favorites.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { each, map, difference, union } from 'lodash'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
songs: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allFavorites: state => state.songs
|
||||
}
|
||||
|
||||
const actions = {
|
||||
toggleLike ({ commit }) {
|
||||
|
||||
},
|
||||
|
||||
addToFavorites ({ commit }, songs) {
|
||||
commit(types.FAVORITE_ADD, songs)
|
||||
},
|
||||
|
||||
removeFromFavorites ({ commit }, songs) {
|
||||
|
||||
},
|
||||
|
||||
clearFavorites ({ commit }) {
|
||||
|
||||
},
|
||||
|
||||
like ({ commit }, songs) {
|
||||
|
||||
},
|
||||
|
||||
unlike ({ commit }, songs) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.FAVORITE_TOGGLE_ONE] (state, { song }) {
|
||||
|
||||
},
|
||||
|
||||
[types.FAVORITE_ADD] (state, { songs }) {
|
||||
state.songs = union(state.songs, [].concat(songs))
|
||||
},
|
||||
|
||||
[types.FAVORITE_REMOVE] (state, { songs }) {
|
||||
|
||||
},
|
||||
|
||||
[types.FAVORITE_CLEAR] (state) {
|
||||
state.songs = []
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
67
resources/assets/js/store/modules/playlists.js
Normal file
67
resources/assets/js/store/modules/playlists.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { each, find, map, difference, union } from 'lodash'
|
||||
|
||||
import { http } from '../../services'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
playlists: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allPlaylists: state => state.playlists,
|
||||
playlistById: state => id => find(state.playlists, { id }),
|
||||
songsInPlaylist: state => playlist => playlist.songs
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initPlaylists ({ dispatch, state, commit, getters }, { playlists }) {
|
||||
return new Promise(resolve => {
|
||||
each(playlists, playlist => {
|
||||
playlist.songs = getters.songsByIds(playlist.songs)
|
||||
})
|
||||
commit(types.PLAYLIST_INIT_STORE, playlists)
|
||||
resolve(state.playlists)
|
||||
})
|
||||
},
|
||||
|
||||
addPlaylist ({ commit }, playlists) {
|
||||
|
||||
},
|
||||
|
||||
removePlaylist ({ commit }, playlists) {
|
||||
|
||||
},
|
||||
|
||||
storePlaylist ({ commit }, { name, songs }) {
|
||||
|
||||
},
|
||||
|
||||
deletePlaylist ({ commit }, playlist) {
|
||||
|
||||
},
|
||||
|
||||
addSongsIntoPlaylist ({ commit }, { playlist, songs }) {
|
||||
|
||||
},
|
||||
|
||||
removeSongsFromPlaylist ({ commit }, { playlist, songs }) {
|
||||
|
||||
},
|
||||
|
||||
updatePlaylist ({ commit }, playlist) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.PLAYLIST_INIT_STORE] (state, playlists) {
|
||||
state.playlists = playlists
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
61
resources/assets/js/store/modules/preferences.js
Normal file
61
resources/assets/js/store/modules/preferences.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { extend, has, each } from 'lodash'
|
||||
|
||||
import { ls } from '../../services'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
let storeKey = ''
|
||||
|
||||
const state = {
|
||||
volume: 7,
|
||||
notify: true,
|
||||
repeatMode: 'NO_REPEAT',
|
||||
showExtraPanel: true,
|
||||
confirmClosing: false,
|
||||
equalizer: {
|
||||
preamp: 0,
|
||||
gains: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
artistsViewMode: null,
|
||||
albumsViewMode: null,
|
||||
selectedPreset: -1,
|
||||
transcodeOnMobile: false
|
||||
}
|
||||
|
||||
const getters = {
|
||||
preferenceByKey: state => key => state[key]
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initPreferences ({ commit, getters }, { currentUser: { preferences }}) {
|
||||
return new Promise(resolve => {
|
||||
commit(types.PREFERENCE_INIT_STORE, {
|
||||
preferences,
|
||||
user: getters.currentUser
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
||||
setPreferences ({ commit }, { key, val }) {
|
||||
commit (types.PREFERENCE_SAVE, { key, val })
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.PREFERENCE_INIT_STORE] (state, { user, preferences }) {
|
||||
storeKey = `preferences_${user.id}`
|
||||
extend(state, ls.get(storeKey, state, {}))
|
||||
// setupProxy()
|
||||
},
|
||||
|
||||
[types.PREFERENCE_SAVE] (state) {
|
||||
ls.set(storeKey, state)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
61
resources/assets/js/store/modules/queue.js
Normal file
61
resources/assets/js/store/modules/queue.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { head, last, each, includes, union, difference, map, shuffle as _shuffle, first } from 'lodash'
|
||||
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
songs: [],
|
||||
current: null
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allQueuedSongs: state => state.songs,
|
||||
firstQueuedSong: state => head(state.songs),
|
||||
lastQueuedSong: state => last(state.songs),
|
||||
containedInQueue: state => song => includes(state.songs, song),
|
||||
indexOfInQueue: state => song => state.songs.indexOf(song),
|
||||
nextInQueue: state => {
|
||||
|
||||
},
|
||||
previousInQueue: state => {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
queue ({ commit }, { songs, replace = true, toTop = true}) {
|
||||
|
||||
},
|
||||
|
||||
queueAfterCurrent ({ commit }, songs) {
|
||||
|
||||
},
|
||||
|
||||
unqueue ({ commit }, songs) {
|
||||
|
||||
},
|
||||
|
||||
moveInQueue ({ commit }, { songs, target }) {
|
||||
|
||||
},
|
||||
|
||||
shuffleQueue ({ commit }) {
|
||||
|
||||
},
|
||||
|
||||
clearQueue ({ commit }) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.QUEUE_QUEUE] (state) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
36
resources/assets/js/store/modules/settings.js
Normal file
36
resources/assets/js/store/modules/settings.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { http } from '../../services'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
settings: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allSettings: state => state.settings
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initSettings ({ commit }, { settings }) {
|
||||
return new Promise(resolve => {
|
||||
commit(types.SETTING_INIT_STORE, settings)
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
||||
updateSettings ({ commit }) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.SETTING_INIT_STORE] (state, settings) {
|
||||
state.settings = settings
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
147
resources/assets/js/store/modules/songs.js
Normal file
147
resources/assets/js/store/modules/songs.js
Normal file
|
@ -0,0 +1,147 @@
|
|||
import Vue from 'vue'
|
||||
import slugify from 'slugify'
|
||||
import { without, map, take, remove, orderBy, each, union, compact } from 'lodash'
|
||||
import isMobile from 'ismobilejs'
|
||||
|
||||
import { secondsToHis, alerts, pluralize } from '../../utils'
|
||||
import { http, ls } from '../../services'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const cache = {}
|
||||
|
||||
const state = {
|
||||
songs: [],
|
||||
recentlyPlayed: [],
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allSongs: state => state.songs,
|
||||
|
||||
songById: state => id => cache[id],
|
||||
|
||||
songsByIds: (state, getters) => ids => ids.map(id => getters.songById(id)),
|
||||
|
||||
guessSong: state => (title, album) => {
|
||||
title = slugify(title.toLowerCase())
|
||||
let found = false
|
||||
each(album.songs, song => {
|
||||
if (slugify(song.title.toLowerCase()) === title) {
|
||||
found = song
|
||||
}
|
||||
})
|
||||
|
||||
return found
|
||||
},
|
||||
|
||||
recentlyPlayedSongs: state => state.recentlyPlayed,
|
||||
|
||||
songShareableUrl: state => song => `${window.location.origin}/#!/song/${song.id}`,
|
||||
|
||||
mostPlayedSongs: state => (n = 10) => {
|
||||
const songs = take(orderBy(state.songs, 'playCount', 'desc'), n)
|
||||
|
||||
// Remove those with playCount=0
|
||||
remove(songs, song => !song.playCount)
|
||||
|
||||
return songs
|
||||
},
|
||||
|
||||
recentlyAddedSongs: state => (n = 10) => take(orderBy(state.songs, 'created_at', 'desc'), n)
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initSongs ({ dispatch, commit, state }, albums) {
|
||||
return new Promise(resolve => {
|
||||
const songs = albums.reduce((songs, album) => {
|
||||
each(album.songs, song => dispatch('setupSong', { song, album }))
|
||||
return songs.concat(album.songs)
|
||||
}, [])
|
||||
|
||||
commit(types.SONG_INIT_STORE, songs)
|
||||
resolve(state.songs)
|
||||
})
|
||||
},
|
||||
|
||||
setupSong({ commit, getters, dispatch }, { song, album }) {
|
||||
return new Promise(resolve => {
|
||||
song.fmtLength = secondsToHis(song.length)
|
||||
song.playCount = 0
|
||||
song.album = album
|
||||
song.liked = false
|
||||
song.lyrics = null
|
||||
song.playbackState = 'stopped'
|
||||
|
||||
if (song.contributing_artist_id) {
|
||||
const artist = getters.artistById(song.contributing_artist_id)
|
||||
dispatch('addAlbumsIntoArtist', { artist, album })
|
||||
song.artist = artist
|
||||
} else {
|
||||
song.artist = getters.artistById(song.album.artist.id)
|
||||
}
|
||||
|
||||
// Cache the song, so that byId() is faster
|
||||
cache[song.id] = song
|
||||
})
|
||||
},
|
||||
|
||||
initInteractions({ commit, state, getters, dispatch }, { interactions }) {
|
||||
return new Promise(resolve => {
|
||||
each(interactions, interaction => {
|
||||
const song = getters.songById(interaction.song_id)
|
||||
|
||||
if (!song) {
|
||||
return
|
||||
}
|
||||
|
||||
commit(types.SET_INTERACTION_DATA, {
|
||||
song,
|
||||
liked: interaction.liked,
|
||||
playCount: interaction.play_count
|
||||
})
|
||||
|
||||
if (song.liked) {
|
||||
dispatch('addToFavorites', song)
|
||||
}
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
||||
registerPlay ({ commit }, song) {
|
||||
|
||||
},
|
||||
|
||||
addRecentlyPlayed ({ commit }, song) {
|
||||
|
||||
},
|
||||
|
||||
scrobble ({ commit }, song) {
|
||||
|
||||
},
|
||||
|
||||
updateSongs ({ commit }, { song, data }) {
|
||||
|
||||
},
|
||||
|
||||
syncUpdatedSong ({ commit }, updatedSong) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.SONG_INIT_STORE] (state, songs) {
|
||||
state.songs = songs
|
||||
},
|
||||
|
||||
[types.SET_INTERACTION_DATA] (state, { song, liked, playCount }) {
|
||||
song.liked = liked
|
||||
song.playCount = playCount
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
109
resources/assets/js/store/modules/users.js
Normal file
109
resources/assets/js/store/modules/users.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
import { each, find, without } from 'lodash'
|
||||
import md5 from 'blueimp-md5'
|
||||
import Vue from 'vue'
|
||||
import NProgress from 'nprogress'
|
||||
|
||||
import { http, ls } from '../../services'
|
||||
import { alerts } from '../../utils'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
const state = {
|
||||
users: [],
|
||||
current: {},
|
||||
jwtToken: ls.get('jwt-token')
|
||||
}
|
||||
|
||||
const getters = {
|
||||
allUsers: state => state.users,
|
||||
userById: state => id => find(state.users, { id }),
|
||||
currentUser: state => state.current,
|
||||
jwtToken: state => state.jwtToken
|
||||
}
|
||||
|
||||
const actions = {
|
||||
initUsers ({ commit }, { users, currentUser }) {
|
||||
return new Promise(resolve => {
|
||||
commit(types.USER_INIT_STORE, users)
|
||||
commit(types.USER_SET_CURRENT, currentUser)
|
||||
each(users, user => commit (types.USER_SET_AVATAR, user))
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
||||
setAvatar ({ commit, state }, user = null) {
|
||||
if (!user) {
|
||||
user = state.current
|
||||
}
|
||||
},
|
||||
|
||||
login ({ commit }, credentials) {
|
||||
NProgress.start()
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
http.post('me', credentials, ({ data }) => {
|
||||
commit(types.USER_SET_JWT_TOKEN, data.token)
|
||||
resolve(data)
|
||||
}, error => reject(error))
|
||||
})
|
||||
},
|
||||
|
||||
logout ({ commit }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
http.delete('me', {}, ({ data }) => {
|
||||
commit(types.USER_DELETE_JWT_TOKEN)
|
||||
resolve(data)
|
||||
}, error => reject(error))
|
||||
})
|
||||
},
|
||||
|
||||
updateProfile ({ commit }, { password }) {
|
||||
|
||||
},
|
||||
|
||||
storeUser ({ commit }, profile) {
|
||||
|
||||
},
|
||||
|
||||
updateUser ({ commit }, { user, profile }) {
|
||||
|
||||
},
|
||||
|
||||
destroyUser ({ commit }, user) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
[types.USER_INIT_STORE] (state, users) {
|
||||
state.users = users
|
||||
},
|
||||
|
||||
[types.USER_SET_CURRENT] (state, currentUser) {
|
||||
state.current = currentUser
|
||||
},
|
||||
|
||||
[types.USER_SET_AVATAR] (state, user) {
|
||||
if (!user) {
|
||||
user = state.current
|
||||
}
|
||||
|
||||
user.avatar = `https://www.gravatar.com/avatar/${md5(user.email)}?s=256`
|
||||
},
|
||||
|
||||
[types.USER_SET_JWT_TOKEN] (state, token) {
|
||||
ls.set('jwt-token', token)
|
||||
state.jwtToken = token
|
||||
},
|
||||
|
||||
[types.USER_DELETE_JWT_TOKEN] (state) {
|
||||
ls.remove('jwt-token')
|
||||
state.jwtToken = null
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
66
resources/assets/js/store/mutation-types.js
Normal file
66
resources/assets/js/store/mutation-types.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
export const GLOBAL_INIT_DATA = 'GLOBAL_INIT_DATA'
|
||||
|
||||
export const SONG_INIT_STORE = 'SONG_INIT_STORE'
|
||||
export const SONG_SETUP = 'SONG_SETUP'
|
||||
export const SONG_INCREASE_PLAY_COUNT = 'SONG_INCREASE_PLAY_COUNT'
|
||||
export const SONG_ADD_RECENTLY_PLAYED = 'SONG_ADD_RECENTLY_PLAYED'
|
||||
|
||||
export const SET_INTERACTION_DATA = 'SET_INTERACTION_DATA'
|
||||
|
||||
export const ALBUM_INIT_STORE = 'ALBUM_INIT_STORE'
|
||||
export const ALBUM_SETUP = 'ALBUM_SETUP'
|
||||
export const ALBUM_ADD = 'ALBUM_ADD'
|
||||
export const ALBUM_ADD_SONGS_INTO_ALBUM = 'ALBUM_ADD_SONGS_INTO_ALBUM'
|
||||
export const ALBUM_REMOVE_SONGS_FROM_ALBUM = 'ALBUM_REMOVE_SONGS_FROM_ALBUM'
|
||||
export const ALBUM_REMOVE = 'ALBUM_REMOVE'
|
||||
|
||||
export const ARTIST_INIT_STORE = 'ARTIST_INIT_STORE'
|
||||
export const ARTIST_SETUP = 'ARTIST_SETUP'
|
||||
export const ARTIST_ADD = 'ARTIST_ADD'
|
||||
export const ARTIST_REMOVE = 'ARTIST_REMOVE'
|
||||
export const ARTIST_ADD_ALBUMS_INTO_ARTIST = 'ARTIST_ADD_ALBUMS_INTO_ARTIST'
|
||||
export const ARTIST_REMOVE_ALBUMS_FROM_ARTIST = 'ARTIST_REMOVE_ALBUMS_FROM_ARTIST'
|
||||
|
||||
export const EQUALIZER_SAVE = 'EQUALIZER_SAVE'
|
||||
export const EQUALIZER_INIT = 'EQUALIZER_INIT'
|
||||
|
||||
export const FAVORITE_TOGGLE_ONE = 'FAVORITE_TOGGLE_ONE'
|
||||
export const FAVORITE_ADD = 'FAVORITE_ADD'
|
||||
export const FAVORITE_REMOVE = 'FAVORITE_REMOVE'
|
||||
export const FAVORITE_CLEAR = 'FAVORITE_CLEAR'
|
||||
export const FAVORITE_LIKE = 'FAVORITE_LIKE'
|
||||
export const FAVORITE_UNLIKE = 'FAVORITE_UNLIKE'
|
||||
|
||||
export const PLAYLIST_INIT_STORE = 'PLAYLIST_INIT_STORE'
|
||||
export const PLAYLIST_OBJECTIFY_SONGS = 'PLAYLIST_OBJECTIFY_SONGS'
|
||||
export const PLAYLIST_ADD = 'PLAYLIST_ADD'
|
||||
export const PLAYLIST_REMOVE = 'PLAYLIST_REMOVE'
|
||||
export const PLAYLIST_STORE = 'PLAYLIST_STORE'
|
||||
export const PLAYLIST_DELETE = 'PLAYLIST_DELETE'
|
||||
export const PLAYLIST_ADD_SONGS = 'PLAYLIST_ADD_SONGS'
|
||||
export const PLAYLIST_REMOVE_SONGS = 'PLAYLIST_REMOVE_SONGS'
|
||||
export const PLAYLIST_UPDATE = 'PLAYLIST_UPDATE'
|
||||
|
||||
export const PREFERENCE_INIT_STORE = 'REFERENCE_INIT_STORE'
|
||||
export const PREFERENCE_SAVE = 'PREFERENCE_SAVE'
|
||||
|
||||
export const QUEUE_QUEUE = 'QUEUE_QUEUE'
|
||||
export const QUEUE_QUEUE_AFTER_CURRENT = 'QUEUE_QUEUE_AFTER_CURRENT'
|
||||
export const QUEUE_UNQUEUE = 'QUEUE_UNQUEUE'
|
||||
export const QUEUE_MOVE = 'QUEUE_MOVE'
|
||||
export const QUEUE_CLEAR = 'QUEUE_CLEAR'
|
||||
export const QUEUE_SET_CURRENT = 'QUEUE_SET_CURRENT'
|
||||
export const QUEUE_SHUFFLE = 'QUEUE_SHUFFLE'
|
||||
|
||||
export const SETTING_INIT_STORE = 'SETTING_INIT_STORE'
|
||||
export const SETTING_UPDATE = 'SETTING_UPDATE'
|
||||
|
||||
export const USER_INIT_STORE = 'USER_INIT_STORE'
|
||||
export const USER_SET_CURRENT = 'USER_SET_CURRENT'
|
||||
export const USER_SET_JWT_TOKEN = 'USER_SET_JWT_TOKEN'
|
||||
export const USER_DELETE_JWT_TOKEN = 'USER_DELETE_JWT_TOKEN'
|
||||
export const USER_SET_AVATAR = 'USER_SET_AVATAR'
|
||||
export const USER_UPDATE_PROFILE = 'USER_UPDATE_PROFILE'
|
||||
export const USER_ADD = 'USER_ADD'
|
||||
export const USER_UPDATE = 'USER_UPDATE'
|
||||
export const USER_DELETE = 'USER_DELETE'
|
11
resources/assets/js/store/mutations.js
Normal file
11
resources/assets/js/store/mutations.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { assign } from 'lodash'
|
||||
|
||||
import * as types from './mutation-types'
|
||||
|
||||
const mutations = {
|
||||
[types.GLOBAL_INIT_DATA] (state, data) {
|
||||
// assign(state, data)
|
||||
}
|
||||
}
|
||||
|
||||
export default mutations
|
22
resources/assets/js/store/state.js
Normal file
22
resources/assets/js/store/state.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const state = {
|
||||
songs: [],
|
||||
albums: [],
|
||||
artists: [],
|
||||
favorites: [],
|
||||
queued: [],
|
||||
interactions: [],
|
||||
users: [],
|
||||
settings: [],
|
||||
currentUser: null,
|
||||
playlists: [],
|
||||
useLastfm: false,
|
||||
useYouTube: false,
|
||||
useiTunes: false,
|
||||
allowDownload: false,
|
||||
currentVersion: '',
|
||||
latestVersion: '',
|
||||
cdnUrl: '',
|
||||
originalMediaPath: ''
|
||||
}
|
||||
|
||||
export default state
|
276
yarn.lock
276
yarn.lock
|
@ -361,6 +361,22 @@ babel-generator@^6.23.0:
|
|||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
babel-helper-bindify-decorators@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.22.0.tgz#d7f5bc261275941ac62acfc4e20dacfb8a3fe952"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-traverse "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-builder-binary-assignment-operator-visitor@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd"
|
||||
dependencies:
|
||||
babel-helper-explode-assignable-expression "^6.22.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-call-delegate@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef"
|
||||
|
@ -379,6 +395,23 @@ babel-helper-define-map@^6.22.0:
|
|||
babel-types "^6.22.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-helper-explode-assignable-expression@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-traverse "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-explode-class@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.22.0.tgz#646304924aa6388a516843ba7f1855ef8dfeb69b"
|
||||
dependencies:
|
||||
babel-helper-bindify-decorators "^6.22.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-traverse "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-function-name@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.22.0.tgz#51f1bdc4bb89b15f57a9b249f33d742816dcbefc"
|
||||
|
@ -389,6 +422,16 @@ babel-helper-function-name@^6.22.0:
|
|||
babel-traverse "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-function-name@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6"
|
||||
dependencies:
|
||||
babel-helper-get-function-arity "^6.22.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.23.0"
|
||||
babel-traverse "^6.23.0"
|
||||
babel-types "^6.23.0"
|
||||
|
||||
babel-helper-get-function-arity@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce"
|
||||
|
@ -418,6 +461,16 @@ babel-helper-regex@^6.22.0:
|
|||
babel-types "^6.22.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-helper-remap-async-to-generator@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383"
|
||||
dependencies:
|
||||
babel-helper-function-name "^6.22.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.22.0"
|
||||
babel-traverse "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-helper-replace-supers@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.22.0.tgz#1fcee2270657548908c34db16bcc345f9850cf42"
|
||||
|
@ -457,6 +510,104 @@ babel-plugin-check-es2015-constants@^6.22.0:
|
|||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-syntax-async-functions@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
|
||||
|
||||
babel-plugin-syntax-async-generators@^6.5.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
|
||||
|
||||
babel-plugin-syntax-class-constructor-call@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416"
|
||||
|
||||
babel-plugin-syntax-class-properties@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
|
||||
|
||||
babel-plugin-syntax-decorators@^6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
|
||||
|
||||
babel-plugin-syntax-do-expressions@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d"
|
||||
|
||||
babel-plugin-syntax-dynamic-import@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
|
||||
|
||||
babel-plugin-syntax-exponentiation-operator@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
|
||||
|
||||
babel-plugin-syntax-export-extensions@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
|
||||
|
||||
babel-plugin-syntax-function-bind@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46"
|
||||
|
||||
babel-plugin-syntax-object-rest-spread@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
|
||||
|
||||
babel-plugin-syntax-trailing-function-commas@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
|
||||
|
||||
babel-plugin-transform-async-generator-functions@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.22.0.tgz#a720a98153a7596f204099cd5409f4b3c05bab46"
|
||||
dependencies:
|
||||
babel-helper-remap-async-to-generator "^6.22.0"
|
||||
babel-plugin-syntax-async-generators "^6.5.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-async-to-generator@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e"
|
||||
dependencies:
|
||||
babel-helper-remap-async-to-generator "^6.22.0"
|
||||
babel-plugin-syntax-async-functions "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-class-constructor-call@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.22.0.tgz#11a4d2216abb5b0eef298b493748f4f2f4869120"
|
||||
dependencies:
|
||||
babel-plugin-syntax-class-constructor-call "^6.18.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.22.0"
|
||||
|
||||
babel-plugin-transform-class-properties@^6.22.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.23.0.tgz#187b747ee404399013563c993db038f34754ac3b"
|
||||
dependencies:
|
||||
babel-helper-function-name "^6.23.0"
|
||||
babel-plugin-syntax-class-properties "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.23.0"
|
||||
|
||||
babel-plugin-transform-decorators@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.22.0.tgz#c03635b27a23b23b7224f49232c237a73988d27c"
|
||||
dependencies:
|
||||
babel-helper-explode-class "^6.22.0"
|
||||
babel-plugin-syntax-decorators "^6.13.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.22.0"
|
||||
babel-types "^6.22.0"
|
||||
|
||||
babel-plugin-transform-do-expressions@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb"
|
||||
dependencies:
|
||||
babel-plugin-syntax-do-expressions "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-arrow-functions@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
|
||||
|
@ -625,6 +776,35 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0:
|
|||
babel-runtime "^6.22.0"
|
||||
regexpu-core "^2.0.0"
|
||||
|
||||
babel-plugin-transform-exponentiation-operator@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d"
|
||||
dependencies:
|
||||
babel-helper-builder-binary-assignment-operator-visitor "^6.22.0"
|
||||
babel-plugin-syntax-exponentiation-operator "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-export-extensions@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653"
|
||||
dependencies:
|
||||
babel-plugin-syntax-export-extensions "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-function-bind@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97"
|
||||
dependencies:
|
||||
babel-plugin-syntax-function-bind "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-object-rest-spread@^6.22.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
|
||||
dependencies:
|
||||
babel-plugin-syntax-object-rest-spread "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-regenerator@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6"
|
||||
|
@ -681,6 +861,41 @@ babel-preset-es2015@^6.18.0:
|
|||
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
|
||||
babel-plugin-transform-regenerator "^6.22.0"
|
||||
|
||||
babel-preset-stage-0@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.22.0.tgz#707eeb5b415da769eff9c42f4547f644f9296ef9"
|
||||
dependencies:
|
||||
babel-plugin-transform-do-expressions "^6.22.0"
|
||||
babel-plugin-transform-function-bind "^6.22.0"
|
||||
babel-preset-stage-1 "^6.22.0"
|
||||
|
||||
babel-preset-stage-1@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.22.0.tgz#7da05bffea6ad5a10aef93e320cfc6dd465dbc1a"
|
||||
dependencies:
|
||||
babel-plugin-transform-class-constructor-call "^6.22.0"
|
||||
babel-plugin-transform-export-extensions "^6.22.0"
|
||||
babel-preset-stage-2 "^6.22.0"
|
||||
|
||||
babel-preset-stage-2@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.22.0.tgz#ccd565f19c245cade394b21216df704a73b27c07"
|
||||
dependencies:
|
||||
babel-plugin-syntax-dynamic-import "^6.18.0"
|
||||
babel-plugin-transform-class-properties "^6.22.0"
|
||||
babel-plugin-transform-decorators "^6.22.0"
|
||||
babel-preset-stage-3 "^6.22.0"
|
||||
|
||||
babel-preset-stage-3@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.22.0.tgz#a4e92bbace7456fafdf651d7a7657ee0bbca9c2e"
|
||||
dependencies:
|
||||
babel-plugin-syntax-trailing-function-commas "^6.22.0"
|
||||
babel-plugin-transform-async-generator-functions "^6.22.0"
|
||||
babel-plugin-transform-async-to-generator "^6.22.0"
|
||||
babel-plugin-transform-exponentiation-operator "^6.22.0"
|
||||
babel-plugin-transform-object-rest-spread "^6.22.0"
|
||||
|
||||
babel-register@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.23.0.tgz#c9aa3d4cca94b51da34826c4a0f9e08145d74ff3"
|
||||
|
@ -1124,9 +1339,9 @@ circular-json@^0.3.1:
|
|||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
|
||||
|
||||
clean-css@4.0.x:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.0.6.tgz#992cf37c1064dafbca7f42b522837b411b87cab5"
|
||||
clean-css@4.0.x, clean-css@^4.0.7:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.0.7.tgz#d8fa8b4d87a125f38fa3d64afc59abfc68ba7790"
|
||||
dependencies:
|
||||
source-map "0.5.x"
|
||||
|
||||
|
@ -1137,12 +1352,6 @@ clean-css@^3.1.9:
|
|||
commander "2.8.x"
|
||||
source-map "0.4.x"
|
||||
|
||||
clean-css@^4.0.7:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.0.7.tgz#d8fa8b4d87a125f38fa3d64afc59abfc68ba7790"
|
||||
dependencies:
|
||||
source-map "0.5.x"
|
||||
|
||||
cli-cursor@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
|
||||
|
@ -1453,19 +1662,28 @@ create-hmac@^1.1.0, create-hmac@^1.1.2:
|
|||
create-hash "^1.1.0"
|
||||
inherits "^2.0.1"
|
||||
|
||||
cross-env@^3.1.3, cross-env@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.1.4.tgz#56e8bca96f17908a6eb1bc2012ca126f92842130"
|
||||
cross-env@^3.1.3, cross-env@^3.2.3:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.2.4.tgz#9e0585f277864ed421ce756f81a980ff0d698aba"
|
||||
dependencies:
|
||||
cross-spawn "^3.0.1"
|
||||
cross-spawn "^5.1.0"
|
||||
is-windows "^1.0.0"
|
||||
|
||||
cross-spawn@^3.0.0, cross-spawn@^3.0.1:
|
||||
cross-spawn@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
|
||||
dependencies:
|
||||
lru-cache "^4.0.1"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
dependencies:
|
||||
lru-cache "^4.0.1"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
crypt@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
|
@ -3030,6 +3248,10 @@ is-utf8@^0.2.0:
|
|||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
|
||||
|
||||
is-windows@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.0.tgz#c61d61020c3ebe99261b781bd3d1622395f547f8"
|
||||
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
|
@ -4275,18 +4497,18 @@ postcss-value-parser@^3.2.3:
|
|||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
|
||||
|
||||
postcss@^5.0.10, postcss@^5.2.11, postcss@^5.2.12:
|
||||
version "5.2.12"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.12.tgz#6a2b15e35dd65634441bb0961fa796904c7890e0"
|
||||
postcss@^5.0.10, postcss@^5.2.12, postcss@^5.2.13:
|
||||
version "5.2.13"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.13.tgz#1be52a32cf2ef58c0d75f1aedb3beabcf257cef3"
|
||||
dependencies:
|
||||
chalk "^1.1.3"
|
||||
js-base64 "^2.1.9"
|
||||
source-map "^0.5.6"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
postcss@^5.2.13:
|
||||
version "5.2.13"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.13.tgz#1be52a32cf2ef58c0d75f1aedb3beabcf257cef3"
|
||||
postcss@^5.2.11:
|
||||
version "5.2.12"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.12.tgz#6a2b15e35dd65634441bb0961fa796904c7890e0"
|
||||
dependencies:
|
||||
chalk "^1.1.3"
|
||||
js-base64 "^2.1.9"
|
||||
|
@ -4855,6 +5077,16 @@ sha.js@^2.3.6:
|
|||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
dependencies:
|
||||
shebang-regex "^1.0.0"
|
||||
|
||||
shebang-regex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
||||
|
||||
shelljs@^0.7.5:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
|
||||
|
@ -5692,6 +5924,10 @@ vuequery@^1.0.0:
|
|||
dependencies:
|
||||
vue "^2.1.6"
|
||||
|
||||
vuex@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.2.1.tgz#a42d0ce18cb0e0359258f84bfd76835ed468c185"
|
||||
|
||||
watchpack@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.2.0.tgz#15d4620f1e7471f13fcb551d5c030d2c3eb42dbb"
|
||||
|
|
Loading…
Reference in a new issue