add eslint

This commit is contained in:
Thomas Amland
2020-08-10 11:11:40 +02:00
parent 9f842bcffe
commit 8e0cc715ab
50 changed files with 2493 additions and 1059 deletions
+91 -77
View File
@@ -1,62 +1,61 @@
import axios, { AxiosRequestConfig, AxiosInstance } from "axios"
import { AuthService } from '@/auth/service';
export type AlbumSort = "alphabeticalByName" | "newest" | "recent" | "frequent" | "random"
import axios, { AxiosRequestConfig, AxiosInstance } from 'axios'
import { AuthService } from '@/auth/service'
export type AlbumSort = 'alphabeticalByName' | 'newest' | 'recent' | 'frequent' | 'random'
export class API {
readonly http: AxiosInstance;
readonly get: (path: string, params?: any) => Promise<any>;
readonly post: (path: string, params?: any) => Promise<any>;
readonly clientName = window.origin || "web";
readonly clientName = window.origin || 'web';
constructor(private auth: AuthService) {
this.http = axios.create({});
this.http = axios.create({})
this.http.interceptors.request.use((config: AxiosRequestConfig) => {
config.params = config.params || {};
config.params = config.params || {}
config.baseURL = this.auth.server
config.params.u = this.auth.username;
config.params.s = this.auth.salt;
config.params.t = this.auth.hash;
config.params.c = this.clientName;
config.params.f = "json";
config.params.v = "1.15.0";
return config;
});
config.params.u = this.auth.username
config.params.s = this.auth.salt
config.params.t = this.auth.hash
config.params.c = this.clientName
config.params.f = 'json'
config.params.v = '1.15.0'
return config
})
this.get = (path: string, params: any = {}) => {
return this.http.get(path, {params}).then(response => {
const subsonicResponse = response.data["subsonic-response"];
if (subsonicResponse.status !== "ok") {
const message = subsonicResponse.error?.message || subsonicResponse.status;
const err = new Error(message);
return Promise.reject(err);
}
return Promise.resolve(subsonicResponse);
return this.http.get(path, { params }).then(response => {
const subsonicResponse = response.data['subsonic-response']
if (subsonicResponse.status !== 'ok') {
const message = subsonicResponse.error?.message || subsonicResponse.status
const err = new Error(message)
return Promise.reject(err)
}
return Promise.resolve(subsonicResponse)
})
}
this.post = (path: string, params: any = {}) => {
return this.http.post(path, params).then(response => {
const subsonicResponse = response.data["subsonic-response"];
if (subsonicResponse.status !== "ok") {
const err = new Error(subsonicResponse.status);
return Promise.reject(err);
}
return Promise.resolve(subsonicResponse);
const subsonicResponse = response.data['subsonic-response']
if (subsonicResponse.status !== 'ok') {
const err = new Error(subsonicResponse.status)
return Promise.reject(err)
}
return Promise.resolve(subsonicResponse)
})
}
}
async getGenres() {
const response = await this.get("rest/getGenres", {});
const response = await this.get('rest/getGenres', {})
return response.genres.genre
.map((item: any) => ({
id: encodeURIComponent(item.value),
name: item.value,
...item,
}))
.sort((a: any, b:any) => a.name.localeCompare(b.name));;
.sort((a: any, b:any) => a.name.localeCompare(b.name))
}
async getGenreDetails(id: string) {
@@ -65,7 +64,7 @@ export class API {
count: 500,
offset: 0,
}
const response = await this.get("rest/getSongsByGenre", params);
const response = await this.get('rest/getSongsByGenre', params)
return {
name: id,
tracks: this.normalizeTrackList(response.songsByGenre.song),
@@ -73,37 +72,37 @@ export class API {
}
async getArtists() {
const data = await this.get("rest/getArtists");
const data = await this.get('rest/getArtists')
return data.artists.index.flatMap((index: any) => index.artist.map((artist: any) => ({
id: artist.id,
name: artist.name,
...artist
})));
})))
}
async getAlbums(sort: AlbumSort, size: number = 500) {
async getAlbums(sort: AlbumSort, size = 500) {
const params = {
type: sort,
offset: "0",
offset: '0',
size: size,
};
const data = await this.get("rest/getAlbumList2", params);
}
const data = await this.get('rest/getAlbumList2', params)
return data.albumList2.album.map((item: any) => ({
...item,
image: item.coverArt ? this.getCoverArtUrl(item) : undefined,
}));
}))
}
async getArtistDetails(id: string) {
const params = { id };
const params = { id }
const [info1, info2] = await Promise.all([
this.get("rest/getArtist", params).then(r => r.artist),
this.get("rest/getArtistInfo2", params).then(r => r.artistInfo2),
this.get('rest/getArtist', params).then(r => r.artist),
this.get('rest/getArtistInfo2', params).then(r => r.artistInfo2),
])
return {
id: info1.id,
name: info1.name,
description: (info2.biography || "").replace(/<a[^>]*>.*?<\/a>/gm, ''),
description: (info2.biography || '').replace(/<a[^>]*>.*?<\/a>/gm, ''),
image: info2.largeImageUrl || info2.mediumImageUrl || info2.smallImageUrl,
lastFmUrl: info2.lastFmUrl,
musicBrainzUrl: info2.musicBrainzId
@@ -114,14 +113,14 @@ export class API {
name: artist.name,
...artist
}))
};
}
}
async getAlbumDetails(id: string) {
const params = {id};
const data = await this.get("rest/getAlbum", params);
const item = data.album;
const image = this.getCoverArtUrl(item);
const params = { id }
const data = await this.get('rest/getAlbum', params)
const item = data.album
const image = this.getCoverArtUrl(item)
const trackList = item.song.map((s: any) => ({
...s,
image,
@@ -131,16 +130,16 @@ export class API {
...item,
image,
song: trackList,
};
}
}
async getPlaylists() {
const response = await this.get("rest/getPlaylists");
const response = await this.get('rest/getPlaylists')
return response.playlists.playlist.map((playlist: any) => ({
...playlist,
name: playlist.name || "(Unnamed)",
name: playlist.name || '(Unnamed)',
image: playlist.songCount > 0 ? this.getCoverArtUrl(playlist) : undefined,
}));
}))
}
async getPlaylist(id: string) {
@@ -149,23 +148,23 @@ export class API {
id,
name: 'Random',
tracks: await this.getRandomSongs(),
};
}
}
const response = await this.get("rest/getPlaylist", { id });
const response = await this.get('rest/getPlaylist', { id })
return {
...response.playlist,
name: response.playlist.name || "(Unnamed)",
name: response.playlist.name || '(Unnamed)',
tracks: this.normalizeTrackList(response.playlist.entry || []),
};
}
}
async createPlaylist(name: string) {
await this.get("rest/createPlaylist", { name });
return this.getPlaylists();
await this.get('rest/createPlaylist', { name })
return this.getPlaylists()
}
async deletePlaylist(id: string) {
await this.get("rest/deletePlaylist", { id });
await this.get('rest/deletePlaylist', { id })
}
async addToPlaylist(playlistId: string, trackId: string) {
@@ -173,7 +172,7 @@ export class API {
playlistId,
songIdToAdd: trackId,
}
await this.get("rest/updatePlaylist", params);
await this.get('rest/updatePlaylist', params)
}
async removeFromPlaylist(playlistId: string, index: string) {
@@ -181,20 +180,20 @@ export class API {
playlistId,
songIndexToRemove: index,
}
await this.get("rest/updatePlaylist", params);
await this.get('rest/updatePlaylist', params)
}
async getRandomSongs() {
const params = {
size: 200,
};
const data = await this.get("rest/getRandomSongs", params);
return this.normalizeTrackList(data.randomSongs.song);
}
const data = await this.get('rest/getRandomSongs', params)
return this.normalizeTrackList(data.randomSongs.song)
}
async getStarred() {
return this
.get("rest/getStarred2")
.get('rest/getStarred2')
.then(r => this.normalizeTrackList(r.starred2.song))
}
@@ -204,7 +203,7 @@ export class API {
albumId: type === 'album' ? id : undefined,
artistId: type === 'artist' ? id : undefined,
}
await this.get("rest/star", params);
await this.get('rest/star', params)
}
async unstar(type: 'track' | 'album' | 'artist', id: string) {
@@ -213,27 +212,27 @@ export class API {
albumId: type === 'album' ? id : undefined,
artistId: type === 'artist' ? id : undefined,
}
await this.get("rest/unstar", params);
await this.get('rest/unstar', params)
}
async search(query: string) {
const params = {
query,
};
const data = await this.get("rest/search3", params);
}
const data = await this.get('rest/search3', params)
return {
tracks: this.normalizeTrackList(data.searchResult3.song || []),
albums: (data.searchResult3.album || []).map((x: any) => this.normalizeAlbumResponse(x)),
artists: (data.searchResult3.artist || []).map((x: any) => this.normalizeArtistResponse(x)),
};
}
}
private normalizeTrackList(items: any[]) {
return items.map((item => ({
return items.map(item => ({
...item,
url: this.getStreamUrl(item.id),
image: this.getCoverArtUrl(item),
})))
}))
}
private normalizeAlbumResponse(item: any) {
@@ -252,14 +251,29 @@ export class API {
private getCoverArtUrl(item: any) {
if (!item.coverArt) {
return undefined;
return undefined
}
const { server, username, salt, hash } = this.auth;
return `${server}/rest/getCoverArt?id=${item.coverArt}&v=1.15.0&u=${username}&s=${salt}&t=${hash}&c=${this.clientName}&size=300`
const { server, username, salt, hash } = this.auth
return `${server}/rest/getCoverArt` +
`?id=${item.coverArt}` +
'&v=1.15.0' +
`&u=${username}` +
`&s=${salt}` +
`&t=${hash}` +
`&c=${this.clientName}` +
'&size=300'
}
private getStreamUrl(id: any) {
const { server, username, salt, hash } = this.auth;
return `${server}/rest/stream?id=${id}&format=raw&v=1.15.0&u=${username}&s=${salt}&t=${hash}&c=${this.clientName}&size=300`
const { server, username, salt, hash } = this.auth
return `${server}/rest/stream` +
`?id=${id}` +
'&format=raw' +
'&v=1.15.0' +
`&u=${username}` +
`&s=${salt}` +
`&t=${hash}` +
`&c=${this.clientName}` +
'&size=300'
}
}
+5 -5
View File
@@ -1,8 +1,8 @@
<template functional>
<a :href="props.href"
target="_blank"
rel="noopener noreferrer"
:class="[data.class, data.staticClass]">
<slot/>
target="_blank"
rel="noopener noreferrer"
:class="[data.class, data.staticClass]">
<slot />
</a>
</template>
</template>
+2 -2
View File
@@ -1,5 +1,5 @@
<template>
<BIcon :icon="icon" v-bind="$attrs"/>
<BIcon :icon="icon" v-bind="$attrs" />
</template>
<script lang="ts">
import Vue from 'vue'
@@ -42,7 +42,7 @@
BIconPersonCircle,
},
props: {
icon: { type: String }
icon: { type: String, required: true }
},
})
</script>
+5 -5
View File
@@ -3,7 +3,7 @@
<div class="fixed-img-inner">
<img v-if="props.src" :src="props.src">
<div v-else class="text-muted">
<Icon icon="music-note-beamed"/>
<Icon icon="music-note-beamed" />
</div>
</div>
</div>
@@ -18,7 +18,7 @@
.fixed-img {
position: relative;
width: 100%;
.tile-img-inner {
position: absolute;
width: 100%;
@@ -42,11 +42,11 @@
}
</style>
<script lang="ts">
import Vue from "vue";
import Vue from 'vue'
export default Vue.extend({
props: {
square: { type: Boolean, default: false },
}
});
</script>
})
</script>
+5 -5
View File
@@ -1,13 +1,13 @@
<template>
<b-dropdown variant="link" boundary="window" no-caret toggle-class="p-0">
<template #button-content>
<Icon icon="three-dots-vertical"/>
<Icon icon="three-dots-vertical" />
</template>
<slot/>
<slot />
</b-dropdown>
</template>
<script lang="ts">
import Vue from "vue";
import Vue from 'vue'
export default Vue.extend({});
</script>
export default Vue.extend({})
</script>
+4 -4
View File
@@ -1,12 +1,12 @@
<template functional>
<div>
<slot v-if="props.data" :data="props.data"></slot>
<slot v-if="props.data" :data="props.data" />
<div v-else class="text-center">
<span class="spinner-grow"/>
<span class="spinner-grow" />
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Vue from 'vue'
export default Vue.extend({})
</script>
</script>
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="tile card">
<router-link class="tile-img" :to="props.to">
<img v-if="props.image" :src="props.image">
<Icon v-else class="tile-img-fallback text-muted" icon="music-note-beamed"/>
<Icon v-else class="tile-img-fallback text-muted" icon="music-note-beamed" />
</router-link>
<div class="card-body">
<div class="text-truncate font-weight-bold">
+4 -4
View File
@@ -1,6 +1,6 @@
<template functional>
<div class="tiles" :class="props.square ? 'tiles-square' : 'tiles-rect'">
<slot></slot>
<slot />
</div>
</template>
<style lang="scss">
@@ -29,11 +29,11 @@
}
</style>
<script lang="ts">
import Vue from "vue";
import Vue from 'vue'
export default Vue.extend({
props: {
square: { type: Boolean, default: false },
}
});
</script>
})
</script>
+11 -11
View File
@@ -1,10 +1,10 @@
import Vue from 'vue';
import ExternalLink from "./ExternalLink.vue";
import Icon from "./Icon.vue";
import OverflowMenu from "./OverflowMenu.vue";
import Spinner from "./Spinner.vue";
import Tiles from "./Tiles.vue";
import Tile from "./Tile.vue";
import Vue from 'vue'
import ExternalLink from './ExternalLink.vue'
import Icon from './Icon.vue'
import OverflowMenu from './OverflowMenu.vue'
import Spinner from './Spinner.vue'
import Tiles from './Tiles.vue'
import Tile from './Tile.vue'
const components = {
ExternalLink,
@@ -13,11 +13,11 @@ const components = {
Spinner,
Tiles,
Tile,
};
}
type Key = keyof typeof components;
Object.keys(components).forEach((_key) => {
const key = _key as keyof typeof components;
Vue.component(key, components[key]);
});
const key = _key as keyof typeof components
Vue.component(key, components[key])
})
+8 -9
View File
@@ -1,12 +1,11 @@
import Vue from 'vue';
import Vue from 'vue'
Vue.filter("duration", (value: number) => {
const minutes = Math.floor(value / 60);
const seconds = Math.floor(value % 60);
return (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
Vue.filter('duration', (value: number) => {
const minutes = Math.floor(value / 60)
const seconds = Math.floor(value % 60)
return (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds
})
Vue.filter("dateTime", (value: string) => {
return value;
})
Vue.filter('dateTime', (value: string) => {
return value
})
+6 -8
View File
@@ -1,4 +1,3 @@
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/auth/Login.vue'
import Queue from '@/player/Queue.vue'
@@ -14,8 +13,7 @@ import Starred from '@/library/starred/Starred.vue'
import Playlist from '@/playlist/Playlist.vue'
import PlaylistList from '@/playlist/PlaylistList.vue'
import SearchResult from '@/search/SearchResult.vue'
import { AuthService } from '@/auth/service';
import { AuthService } from '@/auth/service'
export function setupRouter(auth: AuthService) {
const router = new Router({
@@ -104,15 +102,15 @@ export function setupRouter(auth: AuthService) {
})
},
]
});
})
router.beforeEach((to, from, next) => {
if (to.name !== 'login' && !auth.isAuthenticated()) {
next({name: 'login', query: { returnTo: to.fullPath }});
next({ name: 'login', query: { returnTo: to.fullPath } })
} else {
next();
next()
}
});
})
return router;
return router
}
+21 -23
View File
@@ -1,10 +1,8 @@
import Vue from 'vue'
import Vuex, { Module } from 'vuex'
import { ActionContext } from "vuex"
import { playerModule } from "@/player/store"
import axios from 'axios';
import { AuthService } from '@/auth/service';
import { API } from './api';
import { playerModule } from '@/player/store'
import { AuthService } from '@/auth/service'
import { API } from './api'
interface State {
isLoggedIn: boolean;
@@ -26,48 +24,48 @@ const setupRootModule = (authService: AuthService, api: API): Module<State, any>
},
mutations: {
setError(state, error) {
state.error = error;
state.error = error
},
clearError(state) {
state.error = null;
state.error = null
},
setLoginSuccess(state, { username, server }) {
state.isLoggedIn = true;
state.username = username;
state.server = server;
state.isLoggedIn = true
state.username = username
state.server = server
},
toggleMenu(state) {
state.showMenu = !state.showMenu;
state.showMenu = !state.showMenu
},
setPlaylists(state, playlists: any[]) {
state.playlists = playlists
.sort((a: any, b: any) => b.changed.localeCompare(a.changed));
.sort((a: any, b: any) => b.changed.localeCompare(a.changed))
},
removePlaylist(state, id: string) {
state.playlists = state.playlists.filter(p => p.id !== id);
state.playlists = state.playlists.filter(p => p.id !== id)
},
},
actions: {
loadPlaylists({ commit }) {
api.getPlaylists().then(result => {
commit("setPlaylists", result);
commit('setPlaylists', result)
})
},
createPlaylist({ commit }, name) {
api.createPlaylist(name).then(result => {
commit("setPlaylists", result);
commit('setPlaylists', result)
})
},
addTrackToPlaylist({ }, { playlistId, trackId }) {
api.addToPlaylist(playlistId, trackId);
api.addToPlaylist(playlistId, trackId)
},
deletePlaylist({ commit, state }, id) {
deletePlaylist({ commit }, id) {
api.deletePlaylist(id).then(() => {
commit("removePlaylist", id)
commit('removePlaylist', id)
})
}
},
});
})
export function setupStore(authService: AuthService, api: API) {
const store = new Vuex.Store({
@@ -84,9 +82,9 @@ export function setupStore(authService: AuthService, api: API) {
store.watch(
(state) => state.isLoggedIn,
() => {
store.dispatch("loadPlaylists")
store.dispatch('loadPlaylists')
}
);
)
return store;
return store
}
+7 -7
View File
@@ -1,13 +1,13 @@
import MD5 from 'md5-es';
import MD5 from 'md5-es'
export function randomString(): string {
let arr = new Uint8Array(16);
window.crypto.getRandomValues(arr);
const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
arr = arr.map(x => validChars.charCodeAt(x % validChars.length));
return String.fromCharCode.apply(null, Array.from(arr));
let arr = new Uint8Array(16)
window.crypto.getRandomValues(arr)
const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
arr = arr.map(x => validChars.charCodeAt(x % validChars.length))
return String.fromCharCode.apply(null, Array.from(arr))
}
export function md5(str: string): string {
return MD5.hash(str);
return MD5.hash(str)
}