From 245a819f199fc8a33ecb44e578d4c9ee6018aab4 Mon Sep 17 00:00:00 2001 From: Ben Arc Date: Thu, 29 Apr 2021 22:38:57 +0100 Subject: [PATCH] Table working --- lnbits/extensions/jukebox/crud.py | 28 +++-- lnbits/extensions/jukebox/migrations.py | 1 + lnbits/extensions/jukebox/models.py | 1 + lnbits/extensions/jukebox/static/js/index.js | 114 +++++++++++++----- .../jukebox/templates/jukebox/index.html | 89 +++++++------- lnbits/extensions/jukebox/views_api.py | 38 +++++- 6 files changed, 178 insertions(+), 93 deletions(-) diff --git a/lnbits/extensions/jukebox/crud.py b/lnbits/extensions/jukebox/crud.py index 3cdaf9dc8..01159c8eb 100644 --- a/lnbits/extensions/jukebox/crud.py +++ b/lnbits/extensions/jukebox/crud.py @@ -6,6 +6,7 @@ from lnbits.helpers import urlsafe_short_hash async def create_jukebox( + user: str, wallet: str, title: str, price: int, @@ -19,11 +20,12 @@ async def create_jukebox( juke_id = urlsafe_short_hash() result = await db.execute( """ - INSERT INTO jukebox (id, title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO jukebox (id, user, title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( juke_id, + user, title, wallet, sp_user, @@ -40,12 +42,12 @@ async def create_jukebox( return jukebox -async def update_jukebox(sp_user: str, **kwargs) -> Optional[Jukebox]: +async def update_jukebox(id: str, **kwargs) -> Optional[Jukebox]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE jukebox SET {q} WHERE sp_user = ?", (*kwargs.values(), sp_user) + f"UPDATE jukebox SET {q} WHERE id = ?", (*kwargs.values(), id) ) - row = await db.fetchone("SELECT * FROM jukebox WHERE sp_user = ?", (sp_user,)) + row = await db.fetchone("SELECT * FROM jukebox WHERE id = ?", (id,)) return Jukebox(**row) if row else None @@ -58,16 +60,18 @@ async def get_jukebox_by_user(user: str) -> Optional[Jukebox]: row = await db.fetchone("SELECT * FROM jukebox WHERE sp_user = ?", (user,)) return Jukebox(**row) if row else None +async def get_jukeboxs(user: str) -> List[Jukebox]: + rows = await db.fetchall("SELECT * FROM jukebox WHERE user = ?", (user,)) + for row in rows: + if not row.sp_playlists: + await delete_jukebox(row.id) + rows.remove(row) + return [Jukebox.from_row(row) for row in rows] -async def get_jukeboxs(id: str) -> Optional[Jukebox]: - rows = await db.fetchone("SELECT * FROM jukebox WHERE id = ?", (id,)) - return [Jukebox(**row) for row in rows] - - -async def delete_jukebox(shop: int, item_id: int): +async def delete_jukebox(id: str): await db.execute( """ DELETE FROM jukebox WHERE id = ? """, - (Jukebox, item_id), + (id), ) diff --git a/lnbits/extensions/jukebox/migrations.py b/lnbits/extensions/jukebox/migrations.py index 86f675fe1..2f4e7afd7 100644 --- a/lnbits/extensions/jukebox/migrations.py +++ b/lnbits/extensions/jukebox/migrations.py @@ -6,6 +6,7 @@ async def m001_initial(db): """ CREATE TABLE jukebox ( id TEXT PRIMARY KEY, + user TEXT, title TEXT, wallet TEXT, sp_user TEXT NOT NULL, diff --git a/lnbits/extensions/jukebox/models.py b/lnbits/extensions/jukebox/models.py index dddebbc57..f66219b16 100644 --- a/lnbits/extensions/jukebox/models.py +++ b/lnbits/extensions/jukebox/models.py @@ -9,6 +9,7 @@ from sqlite3 import Row class Jukebox(NamedTuple): id: str + user: str title: str wallet: str sp_user: str diff --git a/lnbits/extensions/jukebox/static/js/index.js b/lnbits/extensions/jukebox/static/js/index.js index bae0a0e7d..3ec79f872 100644 --- a/lnbits/extensions/jukebox/static/js/index.js +++ b/lnbits/extensions/jukebox/static/js/index.js @@ -2,20 +2,63 @@ Vue.component(VueQrcode.name, VueQrcode) -const pica = window.pica() - - +var mapJukebox = obj => { + obj._data = _.clone(obj) + + obj.device = obj.sp_device.split("-")[0] + playlists = obj.sp_playlists.split(",") + var i; + playlistsar = [] + for (i = 0; i < playlists.length; i++) { + playlistsar.push(playlists[i].split("-")[0]) + } + obj.playlist = playlistsar.join() + return obj +} new Vue({ el: '#vue', mixins: [windowMixin], data() { return { + JukeboxTable: { + columns: [ + { + name: 'title', + align: 'left', + label: 'Title', + field: 'title' + }, + { + name: 'device', + align: 'left', + label: 'Device', + field: 'device' + }, + { + name: 'playlist', + align: 'left', + label: 'Playlist', + field: 'playlist' + }, + { + name: 'price', + align: 'left', + label: 'Price', + field: 'price' + }, + ], + pagination: { + rowsPerPage: 10 + } + }, isPwd: true, tokenFetched: true, devices: [], + filter: '', jukebox: {}, playlists: [], + JukeboxLinks: [], step: 1, locationcbPath: "", locationcb: "", @@ -27,20 +70,42 @@ new Vue({ } }, computed: { - printItems() { - return this.jukebox.items.filter(({enabled}) => enabled) - } + }, methods: { + getJukeboxes(){ + self = this + LNbits.api + .request('GET', '/jukebox/api/v1/jukebox', self.g.user.wallets[0].inkey) + .then(function (response) { + self.JukeboxLinks = response.data.map(mapJukebox) + }) + .catch(err => { + LNbits.utils.notifyApiError(err) + }) + }, + deleteJukebox(juke_id){ + self = this + LNbits.api + .request('DELETE', '/jukebox/api/v1/jukebox/' + juke_id, self.g.user.wallets[0].adminkey) + .then(function (response) { + self.JukeboxLinks = _.reject(self.JukeboxLinks, function (obj) { + return obj.id === juke_id + }) + }) + + .catch(err => { + LNbits.utils.notifyApiError(err) + }) + }, closeFormDialog() { this.jukeboxDialog.data = {} this.jukeboxDialog.show = false this.step = 1 }, submitSpotify() { - self = this - console.log(self.jukeboxDialog.data) + self.jukeboxDialog.data.user = self.g.user.id self.requestAuthorization() this.$q.notify({ spinner: true, @@ -56,7 +121,6 @@ new Vue({ .then(response => { if(response.data){ var timerId = setInterval(function(){ - console.log(response.data) if(!self.jukeboxDialog.data.sp_user){ clearInterval(timerId); } @@ -68,15 +132,7 @@ new Vue({ self.jukeboxDialog.data.sp_access_token = response.data.sp_access_token self.step = 3 self.fetchAccessToken() - clearInterval(timerId) - - // self.refreshPlaylists(response.data.sp_token) -// self.$q.notify({ -// message: 'Success! App is now linked!', -// timeout: 3000 -// }) - //set devices, playlists } }) .catch(err => { @@ -97,7 +153,7 @@ new Vue({ url += '&redirect_uri=' + encodeURI(self.locationcbPath) + self.jukeboxDialog.data.sp_user url += "&show_dialog=true" url += '&scope=user-read-private user-read-email user-modify-playback-state user-read-playback-position user-library-read streaming user-read-playback-state user-read-recently-played playlist-read-private' - console.log(url) + window.open(url) }, openNewDialog() { @@ -111,19 +167,16 @@ new Vue({ }, createJukebox(){ self = this - + this.jukeboxDialog.data.sp_playlists = this.jukeboxDialog.data.sp_playlists.join() LNbits.api.request( 'PUT', '/jukebox/api/v1/jukebox/' + this.jukeboxDialog.data.sp_id, self.g.user.wallets[0].adminkey, self.jukeboxDialog.data ) - .then(response => { - console.log(response.data) - - }) - .catch(err => { - LNbits.utils.notifyApiError(err) + .then(function (response) { + self.JukeboxLinks.push(mapJukebox(response.data)) + self.jukeboxDialog.show = false }) }, @@ -156,12 +209,11 @@ new Vue({ xhr.send(body) xhr.onload = function() { let responseObj = JSON.parse(xhr.response) - console.log(responseObj.devices[0]) self.devices = [] var i; for (i = 0; i < responseObj.devices.length; i++) { self.devices.push(responseObj.devices[i].name + "-" + responseObj.devices[i].id) - console.log(responseObj.devices[i].name) + } } @@ -191,20 +243,19 @@ new Vue({ xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.setRequestHeader('Authorization', 'Basic ' + btoa(this.jukeboxDialog.data.sp_user + ":" + this.jukeboxDialog.data.sp_secret)) xhr.send(body) - console.log(('Authorization', 'Basic ' + btoa(this.jukeboxDialog.data.sp_user + ":" + this.jukeboxDialog.data.sp_secret))) xhr.onload = function() { let responseObj = JSON.parse(xhr.response) - alert(responseObj.access_token) - alert(responseObj.refresh_token) self.jukeboxDialog.data.sp_access_token = responseObj.access_token self.jukeboxDialog.data.sp_refresh_token = responseObj.refresh_token - console.log(self.jukeboxDialog.data) self.refreshPlaylists() self.refreshDevices() } }, }, created() { + + var getJukeboxes = this.getJukeboxes + getJukeboxes() this.selectedWallet = this.g.user.wallets[0] this.locationcbPath = String([ window.location.protocol, @@ -212,7 +263,6 @@ new Vue({ window.location.host, '/jukebox/api/v1/jukebox/spotify/cb/' ].join('')) - console.log(this.locationcbPath) this.locationcb = this.locationcbPath } }) diff --git a/lnbits/extensions/jukebox/templates/jukebox/index.html b/lnbits/extensions/jukebox/templates/jukebox/index.html index 07e06ebd9..c865794bf 100644 --- a/lnbits/extensions/jukebox/templates/jukebox/index.html +++ b/lnbits/extensions/jukebox/templates/jukebox/index.html @@ -11,30 +11,36 @@ @click="openNewDialog()" >Add Spotify Jukebox -
-
Items
-
+ {% raw %} + + @@ -253,9 +250,13 @@ >
- Create Jukebox + Create Jukebox
", methods=["DELETE"]) @api_check_wallet_key("admin") async def api_delete_item(juke_id): - shop = await delete_jukebox(juke_id) - return "", HTTPStatus.NO_CONTENT + await delete_jukebox(juke_id) + try: + return ( + jsonify( + [ + { + **jukebox._asdict() + } + for jukebox in await get_jukeboxs(g.wallet.user) + ] + ), + HTTPStatus.OK, + ) + except: + return "", HTTPStatus.NO_CONTENT