Commit bcaa0446 authored by jackie / Andrea Ida Malkah Klaura's avatar jackie / Andrea Ida Malkah Klaura
Browse files

META: switching to vue/recommended linting

Our linting config in package.json was:
```
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
```

Now switching to "plugin:vue/recommended" and apply all auto-fixes
parent 34b66db6
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"node": true "node": true
}, },
"extends": [ "extends": [
"plugin:vue/essential", "plugin:vue/recommended",
"eslint:recommended" "eslint:recommended"
], ],
"rules": { "rules": {
......
<template> <template>
<div id="app"> <div id="app">
<app-header v-bind:modules="modules" v-bind:user="user"></app-header> <app-header
<router-view/> :modules="modules"
<app-footer></app-footer> :user="user"
/>
<router-view />
<app-footer />
</div> </div>
</template> </template>
...@@ -15,7 +18,7 @@ import footer from './components/Footer.vue' ...@@ -15,7 +18,7 @@ import footer from './components/Footer.vue'
import axios from 'axios' import axios from 'axios'
export default { export default {
name: 'app', name: 'App',
components: { components: {
'app-header': header, 'app-header': header,
'app-footer': footer 'app-footer': footer
...@@ -66,6 +69,27 @@ export default { ...@@ -66,6 +69,27 @@ export default {
else return this.modules_logged_out else return this.modules_logged_out
} }
}, },
mounted () {
// TODO: remove oidc logging after thorough testing
oidc.Log.logger = console
let self = this
this.oidcmgr.events.addAccessTokenExpiring(function () {
console.log('starting silent access_token renewal')
self.oidcmgr.signinSilent().then(function (user) {
self.user.access_token = user.access_token
console.log(self.user.access_token)
}).catch(function (err) {
console.log(err)
alert('Your OpenID access token could not be renewed automatically.\n' +
'You will be logged out in ' + process.env.VUE_APP_API_STEERING_OIDC_EXPIRE_NOTIFICATION + ' seconds.')
})
})
this.oidcmgr.events.addAccessTokenExpired(function () {
console.log('expired!')
self.signOut()
})
this.getOIDCUser()
},
methods: { methods: {
signIn () { signIn () {
this.oidcmgr.signinRedirect().catch(function (err) { this.oidcmgr.signinRedirect().catch(function (err) {
...@@ -133,27 +157,6 @@ export default { ...@@ -133,27 +157,6 @@ export default {
console.log(new Date(user.expires_at * 1000).toUTCString()) console.log(new Date(user.expires_at * 1000).toUTCString())
console.log(user.access_token) console.log(user.access_token)
} }
},
mounted () {
// TODO: remove oidc logging after thorough testing
oidc.Log.logger = console
let self = this
this.oidcmgr.events.addAccessTokenExpiring(function () {
console.log('starting silent access_token renewal')
self.oidcmgr.signinSilent().then(function (user) {
self.user.access_token = user.access_token
console.log(self.user.access_token)
}).catch(function (err) {
console.log(err)
alert('Your OpenID access token could not be renewed automatically.\n' +
'You will be logged out in ' + process.env.VUE_APP_API_STEERING_OIDC_EXPIRE_NOTIFICATION + ' seconds.')
})
})
this.oidcmgr.events.addAccessTokenExpired(function () {
console.log('expired!')
self.signOut()
})
this.getOIDCUser()
} }
} }
</script> </script>
......
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
<b-container> <b-container>
<h1>Credits</h1> <h1>Credits</h1>
<p> <p>
autoradio/<b>dashboard</b><br /> autoradio/<b>dashboard</b><br>
... developed under the GNU General Public License, by<br /> ... developed under the GNU General Public License, by<br>
<ul> <ul>
<li>Andrea Ida Malkah Klaura <a href="mailto:jackie@o94.at">jackie@o94.at</a></li> <li>Andrea Ida Malkah Klaura <a href="mailto:jackie@o94.at">jackie@o94.at</a></li>
<li>...</li> <li>...</li>
</ul> </ul>
</p> </p>
<p> <p>
<b>Graphics &amp; Icons</b><br /> <b>Graphics &amp; Icons</b><br>
<ul> <ul>
<li>animated loading icon: <a href="https://loading.io/spinner">spinner by loading.io</a>, CC-BY License</li> <li>animated loading icon: <a href="https://loading.io/spinner">spinner by loading.io</a>, CC-BY License</li>
<li>all other Icons: <a href="http://tango.freedesktop.org/">Tango Project</a>, Public Domain</li> <li>all other Icons: <a href="http://tango.freedesktop.org/">Tango Project</a>, Public Domain</li>
......
...@@ -6,13 +6,19 @@ ...@@ -6,13 +6,19 @@
a productive version. a productive version.
</p> </p>
<p> <p>
Here we go: <b-button size="lg" variant="warning" @click="debug()">Debug now!</b-button> Here we go: <b-button
size="lg"
variant="warning"
@click="debug()"
>
Debug now!
</b-button>
</p> </p>
Response headers: <br /> Response headers: <br>
<div style="border: 1px dotted #aaa"> <div style="border: 1px dotted #aaa">
{{ response.headers }} {{ response.headers }}
</div> </div>
Response data: <br /> Response data: <br>
<div style="border: 1px dotted #aaa"> <div style="border: 1px dotted #aaa">
{{ response.data }} {{ response.data }}
</div> </div>
......
...@@ -5,12 +5,22 @@ ...@@ -5,12 +5,22 @@
<h3>Dateien und Playlists</h3> <h3>Dateien und Playlists</h3>
</b-col> </b-col>
<b-col align="right"> <b-col align="right">
<b-dropdown id="ddshows" text="Sendereihe auswählen" variant="info"> <b-dropdown
<b-dropdown-item v-for="(show, index) in this.shows" :key="show.id" v-on:click="switchShow(index)">{{ show.name }}</b-dropdown-item> id="ddshows"
text="Sendereihe auswählen"
variant="info"
>
<b-dropdown-item
v-for="(show, index) in this.shows"
:key="show.id"
@click="switchShow(index)"
>
{{ show.name }}
</b-dropdown-item>
</b-dropdown> </b-dropdown>
</b-col> </b-col>
</b-row> </b-row>
<hr /> <hr>
<b-jumbotron> <b-jumbotron>
<template slot="header"> <template slot="header">
<span v-if="loaded.shows"> <span v-if="loaded.shows">
...@@ -21,11 +31,23 @@ ...@@ -21,11 +31,23 @@
<template slot="lead"> <template slot="lead">
<span v-if="loaded.shows">{{ shows[currentShow].short_description }}</span> <span v-if="loaded.shows">{{ shows[currentShow].short_description }}</span>
</template> </template>
<hr /> <hr>
<div align="center"> <div align="center">
<b-button-group> <b-button-group>
<b-button size="lg" :variant="button.files" @click="switchMode('files')">Files</b-button> <b-button
<b-button size="lg" :variant="button.playlists" @click="switchMode('playlists')">Playlists</b-button> size="lg"
:variant="button.files"
@click="switchMode('files')"
>
Files
</b-button>
<b-button
size="lg"
:variant="button.playlists"
@click="switchMode('playlists')"
>
Playlists
</b-button>
</b-button-group> </b-button-group>
</div> </div>
</b-jumbotron> </b-jumbotron>
...@@ -34,86 +56,200 @@ ...@@ -34,86 +56,200 @@
<div v-if="!loaded.files"> <div v-if="!loaded.files">
<b-row> <b-row>
<b-col align="center"> <b-col align="center">
<img src="../assets/radio.gif" alt="loading data" /> <img
src="../assets/radio.gif"
alt="loading data"
>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
<div v-else> <div v-else>
<b-modal id="modal-add-file" title="Add new file" @ok="addFile"> <b-modal
id="modal-add-file"
title="Add new file"
@ok="addFile"
>
<div v-if="addNewFileURI"> <div v-if="addNewFileURI">
<b-row> <b-row>
<b-col md="2"> <b-col md="2">
<b>Link:</b> <b>Link:</b>
</b-col> </b-col>
<b-col> <b-col>
<b-form-input type="url" v-model="uploadSourceURI" placeholder="Insert a HTTP(S) link here"></b-form-input> <b-form-input
v-model="uploadSourceURI"
type="url"
placeholder="Insert a HTTP(S) link here"
/>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
<div v-else> <div v-else>
<b-form-file v-model="uploadSourceFile" accept="audio/*" placeholder="Choose a file..." drop-placeholder="Drop file here..."></b-form-file> <b-form-file
v-model="uploadSourceFile"
accept="audio/*"
placeholder="Choose a file..."
drop-placeholder="Drop file here..."
/>
</div> </div>
<hr> <hr>
<div align="center"> <div align="center">
<b-form-checkbox v-model="addNewFileURI" value="true" unchecked_value="false"> <b-form-checkbox
v-model="addNewFileURI"
value="true"
unchecked_value="false"
>
Download from remote source instead of uploading a file Download from remote source instead of uploading a file
</b-form-checkbox> </b-form-checkbox>
</div> </div>
</b-modal> </b-modal>
<b-modal id="modal-edit-file" title="Edit meta information" size="lg" @ok="saveFile"> <b-modal
id="modal-edit-file"
title="Edit meta information"
size="lg"
@ok="saveFile"
>
<b-row> <b-row>
<b-col md="2">Artist:</b-col> <b-col md="2">
<b-col><b-form-input v-model="temp.artist" type="text"></b-form-input></b-col> Artist:
</b-col>
<b-col>
<b-form-input
v-model="temp.artist"
type="text"
/>
</b-col>
</b-row> </b-row>
<b-row> <b-row>
<b-col md="2">Album:</b-col> <b-col md="2">
<b-col><b-form-input v-model="temp.album" type="text"></b-form-input></b-col> Album:
</b-col>
<b-col>
<b-form-input
v-model="temp.album"
type="text"
/>
</b-col>
</b-row> </b-row>
<b-row> <b-row>
<b-col md="2">Title:</b-col> <b-col md="2">
<b-col><b-form-input v-model="temp.title" type="text"></b-form-input></b-col> Title:
</b-col>
<b-col>
<b-form-input
v-model="temp.title"
type="text"
/>
</b-col>
</b-row> </b-row>
<hr /> <hr>
<b-row> <b-row>
<b-col md="2">Sourced from:</b-col> <b-col md="2">
Sourced from:
</b-col>
<b-col>{{ temp.uri }}</b-col> <b-col>{{ temp.uri }}</b-col>
</b-row> </b-row>
</b-modal> </b-modal>
<div v-if="files.length === 0" align="center"> <div
<b-alert show variant="warning">There are no files for this show yet.</b-alert> v-if="files.length === 0"
<b-button variant="success" v-b-modal.modal-add-file>Upload or add a file</b-button> align="center"
>
<b-alert
show
variant="warning"
>
There are no files for this show yet.
</b-alert>
<b-button
v-b-modal.modal-add-file
variant="success"
>
Upload or add a file
</b-button>
</div> </div>
<div v-else> <div v-else>
<div align="center" style="padding-bottom: 1.5em;"> <div
<b-button variant="success" v-b-modal.modal-add-file>Upload or add a file</b-button> align="center"
style="padding-bottom: 1.5em;"
>
<b-button
v-b-modal.modal-add-file
variant="success"
>
Upload or add a file
</b-button>
</div> </div>
<b-table ref="filesTable" striped :fields="filesTableFields" :items="files"> <b-table
<template slot="metadata.album" slot-scope="data"> ref="filesTable"
<span v-if="data.item.source.import.state !== 'done'"><img src="../assets/radio.gif" width="24" alt="loading data" /></span> striped
:fields="filesTableFields"
:items="files"
>
<template
slot="metadata.album"
slot-scope="data"
>
<span v-if="data.item.source.import.state !== 'done'"><img
src="../assets/radio.gif"
width="24"
alt="loading data"
></span>
<span v-else>{{ data.value }}</span> <span v-else>{{ data.value }}</span>
</template> </template>
<template slot="metadata.title" slot-scope="data"> <template
slot="metadata.title"
slot-scope="data"
>
<span v-if="data.item.source.import.state === 'done'">{{ data.value }}</span> <span v-if="data.item.source.import.state === 'done'">{{ data.value }}</span>
<span v-else-if="data.item.source.import.progress !== undefined">{{ data.item.source.import.progress.step }} :</span> <span v-else-if="data.item.source.import.progress !== undefined">{{ data.item.source.import.progress.step }} :</span>
</template> </template>
<template slot="duration" slot-scope="data"> <template
<div v-if="data.item.source.import.state === 'done'">{{ prettyNanoseconds(data.value) }}</div> slot="duration"
slot-scope="data"
>
<div v-if="data.item.source.import.state === 'done'">
{{ prettyNanoseconds(data.value) }}
</div>
<div v-else-if="data.item.source.import.progress !== undefined"> <div v-else-if="data.item.source.import.progress !== undefined">
<div v-if="data.item.source.import.progress.step === 'fetching'"> <div v-if="data.item.source.import.progress.step === 'fetching'">
<b-progress :value="data.item.source.import.progress.progress" :max="1" show-progress variant="info" animated></b-progress> <b-progress
:value="data.item.source.import.progress.progress"
:max="1"
show-progress
variant="info"
animated
/>
</div> </div>
<div v-else> <div v-else>
<b-progress :value="data.item.source.import.progress.progress" :max="1" show-progress variant="success" animated></b-progress> <b-progress
:value="data.item.source.import.progress.progress"
:max="1"
show-progress
variant="success"
animated
/>
</div> </div>
</div> </div>
</template> </template>
<template slot="size" slot-scope="data"> <template
slot="size"
slot-scope="data"
>
<span v-if="data.item.source.import.state === 'done'">{{ prettyFileSize(data.value) }}</span> <span v-if="data.item.source.import.state === 'done'">{{ prettyFileSize(data.value) }}</span>
</template> </template>
<template slot="actions" slot-scope="data"> <template
slot="actions"
slot-scope="data"
>
<b-button-group size="sm"> <b-button-group size="sm">
<b-button @click="editFile(data.item.id)">Edit</b-button> <b-button @click="editFile(data.item.id)">
<b-button variant="danger" @click="deleteFile(data.item.id)">Delete</b-button> Edit
</b-button>
<b-button
variant="danger"
@click="deleteFile(data.item.id)"
>
Delete
</b-button>
</b-button-group> </b-button-group>
</template> </template>
</b-table> </b-table>
...@@ -125,17 +261,36 @@ ...@@ -125,17 +261,36 @@
<div v-if="!loaded.playlists"> <div v-if="!loaded.playlists">
<b-row> <b-row>
<b-col align="center"> <b-col align="center">
<img src="../assets/radio.gif" alt="loading data" /> <img
src="../assets/radio.gif"
alt="loading data"
>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
<div v-else> <div v-else>
<div v-if="playlists.length === 0" align="center"> <div
<b-alert show variant="warning">There are no playlists for this show yet.</b-alert> v-if="playlists.length === 0"
<b-button variant="success" @click="notYetImplemented">Create a playlist</b-button> align="center"
>
<b-alert
show
variant="warning"
>
There are no playlists for this show yet.
</b-alert>
<b-button
variant="success"
@click="notYetImplemented"
>
Create a playlist
</b-button>
</div> </div>
<div v-else> <div v-else>
<b-table striped :items="playlistsTable" /> <b-table
striped
:items="playlistsTable"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -148,6 +303,7 @@ import filesize from 'filesize' ...@@ -148,6 +303,7 @@ import filesize from 'filesize'
import prettyDate from '../mixins/prettyDate' import prettyDate from '../mixins/prettyDate'
export default { export default {
mixins: [ prettyDate ],
data () { data () {
return { return {
shows: [], // an array of objects describing our shows (empty at load, will be populated on created()) shows: [], // an array of objects describing our shows (empty at load, will be populated on created())
...@@ -186,7 +342,6 @@ export default { ...@@ -186,7 +342,6 @@ export default {
] ]
} }
}, },
mixins: [ prettyDate ],
computed: { computed: {
playlistsTable: function (){ playlistsTable: function (){
var arr = [] var arr = []
...@@ -201,6 +356,33 @@ export default { ...@@ -201,6 +356,33 @@ export default {
return arr return arr
} }
}, },
created () {
// when we enter this module, we want to load all shows of the current user
// before we search for corresponding shows in the tank
var uri = process.env.VUE_APP_API_STEERING_SHOWS
// only the superuser should see all shows and therefore files and playlists
// normal users should only see their own shows
if (!this.$parent.user.steeringUser.is_superuser) {
uri += '?owner=' + this.$parent.user.steeringUser.id
}
// now make the API call to fetch the shows
axios.get(uri, {
withCredentials: true,
headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
}).then(response => {
if (response.data.length === 0) {
alert('There are now shows associated with your account!')
return
}
this.shows = response.data
this.currentShowID = this.shows[0].id
this.currentShow = 0
this.loaded.shows = true
this.switchShow(this.currentShow)
}).catch(error => {
alert('There was an error fetching shows from steering: ' + error)
})
},
methods: { methods: {
notYetImplemented: function () { notYetImplemented: function () {
alert('By the mighty witchcraftry of the mother of time!\n\nThis feature is not implemented yet.') alert('By the mighty witchcraftry of the mother of time!\n\nThis feature is not implemented yet.')
...@@ -439,33 +621,6 @@ export default { ...@@ -439,33 +621,6 @@ export default {
alert('There was an error fetching playlists from tank: ' + error) alert('There was an error fetching playlists from tank: ' + error)
}) })
} }