This commit is contained in:
Ben Arc 2021-06-24 01:40:24 +01:00
parent e7824e0e8d
commit e51ef5b722
8 changed files with 449 additions and 226 deletions

View File

@ -82,7 +82,7 @@
<script>
Vue.component(VueQrcode.name, VueQrcode)
Vue.use(VueQrcodeReader)
var mapEvents = function(obj) {
var mapEvents = function (obj) {
obj.date = Quasar.utils.date.formatDate(
new Date(obj.time * 1000),
'YYYY-MM-DD HH:mm'
@ -94,7 +94,7 @@
new Vue({
el: '#vue',
mixins: [windowMixin],
data: function() {
data: function () {
return {
tickets: [],
ticketsTable: {
@ -119,35 +119,35 @@
}
},
methods: {
hoverEmail: function(tmp) {
hoverEmail: function (tmp) {
this.tickets.data.emailtemp = tmp
},
closeCamera: function() {
closeCamera: function () {
this.sendCamera.show = false
},
showCamera: function() {
showCamera: function () {
this.sendCamera.show = true
},
decodeQR: function(res) {
decodeQR: function (res) {
this.sendCamera.show = false
var self = this
LNbits.api
.request('GET', '/events/api/v1/register/ticket/' + res)
.then(function(response) {
.then(function (response) {
self.$q.notify({
type: 'positive',
message: 'Registered!'
})
setTimeout(function() {
setTimeout(function () {
window.location.reload()
}, 2000)
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
getEventTickets: function() {
getEventTickets: function () {
var self = this
console.log('obj')
LNbits.api
@ -155,17 +155,17 @@
'GET',
'/events/api/v1/eventtickets/{{ wallet_id }}/{{ event_id }}'
)
.then(function(response) {
self.tickets = response.data.map(function(obj) {
.then(function (response) {
self.tickets = response.data.map(function (obj) {
return mapEvents(obj)
})
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
}
},
created: function() {
created: function () {
this.getEventTickets()
}
})

View File

@ -93,7 +93,11 @@ new Vue({
getJukeboxes() {
self = this
LNbits.api
.request('GET', '/jukebox/api/v1/jukebox', self.g.user.wallets[0].adminkey)
.request(
'GET',
'/jukebox/api/v1/jukebox',
self.g.user.wallets[0].adminkey
)
.then(function (response) {
self.JukeboxLinks = response.data.map(mapJukebox)
})
@ -165,10 +169,10 @@ new Vue({
LNbits.utils.notifyApiError(err)
})
},
authAccess() {
authAccess() {
self = this
self.requestAuthorization()
self.getSpotifyTokens()
self.requestAuthorization()
self.getSpotifyTokens()
self.$q.notify({
spinner: true,
message: 'Processing',
@ -195,37 +199,37 @@ new Vue({
if (self.jukeboxDialog.data.sp_access_token) {
self.refreshPlaylists()
self.refreshDevices()
console.log("this.devices")
console.log('this.devices')
console.log(self.devices)
console.log("this.devices")
console.log('this.devices')
setTimeout(function () {
if (self.devices.length < 1 || self.playlists.length < 1) {
self.$q.notify({
spinner: true,
color: 'red',
message:
'Error! Make sure Spotify is open on the device you wish to use, has playlists, and is playing something',
timeout: 10000
})
LNbits.api
.request(
'DELETE',
'/jukebox/api/v1/jukebox/' + response.data.id,
self.g.user.wallets[0].adminkey
)
.then(function (response) {
self.getJukeboxes()
if (self.devices.length < 1 || self.playlists.length < 1) {
self.$q.notify({
spinner: true,
color: 'red',
message:
'Error! Make sure Spotify is open on the device you wish to use, has playlists, and is playing something',
timeout: 10000
})
.catch(err => {
LNbits.utils.notifyApiError(err)
})
clearInterval(timerId)
self.closeFormDialog()
} else {
self.step = 4
clearInterval(timerId)
}
}, 2000)
LNbits.api
.request(
'DELETE',
'/jukebox/api/v1/jukebox/' + response.data.id,
self.g.user.wallets[0].adminkey
)
.then(function (response) {
self.getJukeboxes()
})
.catch(err => {
LNbits.utils.notifyApiError(err)
})
clearInterval(timerId)
self.closeFormDialog()
} else {
self.step = 4
clearInterval(timerId)
}
}, 2000)
}
}
})
@ -347,15 +351,15 @@ new Vue({
}
}
},
refreshDevices() {
refreshDevices() {
self = this
self.deviceApi(
self.deviceApi(
'GET',
'https://api.spotify.com/v1/me/player/devices',
null
)
},
fetchAccessToken(code) {
fetchAccessToken(code) {
self = this
let body = 'grant_type=authorization_code'
body += '&code=' + code
@ -363,16 +367,16 @@ new Vue({
'&redirect_uri=' +
encodeURI(self.locationcbPath + self.jukeboxDialog.data.sp_id)
self.callAuthorizationApi(body)
self.callAuthorizationApi(body)
},
refreshAccessToken() {
refreshAccessToken() {
self = this
let body = 'grant_type=refresh_token'
body += '&refresh_token=' + self.jukeboxDialog.data.sp_refresh_token
body += '&client_id=' + self.jukeboxDialog.data.sp_user
self.callAuthorizationApi(body)
self.callAuthorizationApi(body)
},
callAuthorizationApi(body) {
callAuthorizationApi(body) {
self = this
console.log(
btoa(

View File

@ -6,14 +6,9 @@ new Vue({
el: '#vue',
mixins: [windowMixin],
data() {
return {
}
return {}
},
computed: {},
methods: {
},
created() {
}
methods: {},
created() {}
})

View File

@ -1,24 +1,33 @@
<q-card-section>
To use this extension you need a Spotify client ID and client secret. You
get these by creating an app in the Spotify developers dashboard
<a style="color:#43a047" href="https://developer.spotify.com/dashboard/applications">here </a>
<br /><br />Select the playlists you want people to be able to pay for,
share the frontend page, profit :) <br /><br />
Made by, <a style="color:#43a047" href="https://twitter.com/arcbtc">benarc</a>. Inspired by,
<a style="color:#43a047" href="https://twitter.com/pirosb3/status/1056263089128161280">pirosb3</a>.
To use this extension you need a Spotify client ID and client secret. You get
these by creating an app in the Spotify developers dashboard
<a
style="color: #43a047"
href="https://developer.spotify.com/dashboard/applications"
>here
</a>
<br /><br />Select the playlists you want people to be able to pay for, share
the frontend page, profit :) <br /><br />
Made by,
<a style="color: #43a047" href="https://twitter.com/arcbtc">benarc</a>.
Inspired by,
<a
style="color: #43a047"
href="https://twitter.com/pirosb3/status/1056263089128161280"
>pirosb3</a
>.
</q-card-section>
<q-expansion-item group="extras" icon="swap_vertical_circle" label="API info" :content-inset-level="0.5">
<q-expansion-item
group="extras"
icon="swap_vertical_circle"
label="API info"
:content-inset-level="0.5"
>
<q-expansion-item group="api" dense expand-separator label="List jukeboxes">
<q-card>
<q-card-section>
<code><span class="text-blue">GET</span>
/jukebox/api/v1/jukebox</code>
<code><span class="text-blue">GET</span> /jukebox/api/v1/jukebox</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
@ -27,7 +36,8 @@
</h5>
<code>[&lt;jukebox_object&gt;, ...]</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X GET {{ request.url_root }}api/v1/jukebox -H "X-Api-Key: {{
<code
>curl -X GET {{ request.url_root }}api/v1/jukebox -H "X-Api-Key: {{
g.user.wallets[0].adminkey }}"
</code>
</q-card-section>
@ -36,8 +46,10 @@
<q-expansion-item group="api" dense expand-separator label="Get jukebox">
<q-card>
<q-card-section>
<code><span class="text-blue">GET</span>
/jukebox/api/v1/jukebox/&lt;juke_id&gt;</code>
<code
><span class="text-blue">GET</span>
/jukebox/api/v1/jukebox/&lt;juke_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
@ -46,36 +58,44 @@
</h5>
<code>&lt;jukebox_object&gt;</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X GET {{ request.url_root }}api/v1/jukebox/&lt;juke_id&gt; -H "X-Api-Key: {{
g.user.wallets[0].adminkey }}"
<code
>curl -X GET {{ request.url_root }}api/v1/jukebox/&lt;juke_id&gt; -H
"X-Api-Key: {{ g.user.wallets[0].adminkey }}"
</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Create/update track">
<q-expansion-item
group="api"
dense
expand-separator
label="Create/update track"
>
<q-card>
<q-card-section>
<code><span class="text-green">POST/PUT</span>
/jukebox/api/v1/jukebox/</code>
<code
><span class="text-green">POST/PUT</span>
/jukebox/api/v1/jukebox/</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">
Body (application/json)
</h5>
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<h5 class="text-caption q-mt-sm q-mb-none">
Returns 200 OK (application/json)
</h5>
<code>&lt;jukbox_object&gt;</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X POST {{ request.url_root }}api/v1/jukebox/ -d
'{"user": &lt;string, user_id&gt;,
"title": &lt;string&gt;, "wallet":&lt;string&gt;, "sp_user":
&lt;string, spotify_user_account&gt;, "sp_secret": &lt;string, spotify_user_secret&gt;, "sp_access_token":
&lt;string, not_required&gt;, "sp_refresh_token":
&lt;string, not_required&gt;, "sp_device": &lt;string, spotify_user_secret&gt;, "sp_playlists":
&lt;string, not_required&gt;, "price":
&lt;integer, not_required&gt;}' -H "Content-type:
application/json" -H "X-Api-Key: {{g.user.wallets[0].adminkey }}"
<code
>curl -X POST {{ request.url_root }}api/v1/jukebox/ -d '{"user":
&lt;string, user_id&gt;, "title": &lt;string&gt;,
"wallet":&lt;string&gt;, "sp_user": &lt;string,
spotify_user_account&gt;, "sp_secret": &lt;string,
spotify_user_secret&gt;, "sp_access_token": &lt;string,
not_required&gt;, "sp_refresh_token": &lt;string, not_required&gt;,
"sp_device": &lt;string, spotify_user_secret&gt;, "sp_playlists":
&lt;string, not_required&gt;, "price": &lt;integer, not_required&gt;}'
-H "Content-type: application/json" -H "X-Api-Key:
{{g.user.wallets[0].adminkey }}"
</code>
</q-card-section>
</q-card>
@ -83,8 +103,10 @@
<q-expansion-item group="api" dense expand-separator label="Delete jukebox">
<q-card>
<q-card-section>
<code><span class="text-red">DELETE</span>
/jukebox/api/v1/jukebox/&lt;juke_id&gt;</code>
<code
><span class="text-red">DELETE</span>
/jukebox/api/v1/jukebox/&lt;juke_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
@ -93,9 +115,11 @@
</h5>
<code>&lt;jukebox_object&gt;</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X DELETE {{ request.url_root }}api/v1/jukebox/&lt;juke_id&gt; -H "X-Api-Key: {{
g.user.wallets[0].adminkey }}"
<code
>curl -X DELETE {{ request.url_root }}api/v1/jukebox/&lt;juke_id&gt;
-H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
</code>
</q-card-section>
</q-card>
</q-expansion-item>
</q-expansion-item></q-expansion-item
>

View File

@ -12,7 +12,9 @@
style="font-size: 20rem"
></q-icon>
<h5 class="q-my-none">Ask the host to turn on the device and launch spotify</h5>
<h5 class="q-my-none">
Ask the host to turn on the device and launch spotify
</h5>
<br />
</center>
</q-card-section>

View File

@ -4,18 +4,36 @@
<div class="col-12 col-md-7 q-gutter-y-md">
<q-card>
<q-card-section>
<q-btn unelevated color="green-7" class="q-ma-lg" @click="openNewDialog()">Add Spotify Jukebox</q-btn>
<q-btn
unelevated
color="green-7"
class="q-ma-lg"
@click="openNewDialog()"
>Add Spotify Jukebox</q-btn
>
{% raw %}
<q-table flat dense :data="JukeboxLinks" row-key="id" :columns="JukeboxTable.columns"
:pagination.sync="JukeboxTable.pagination" :filter="filter">
<q-table
flat
dense
:data="JukeboxLinks"
row-key="id"
:columns="JukeboxTable.columns"
:pagination.sync="JukeboxTable.pagination"
:filter="filter"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props" auto-width>
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
auto-width
>
<div v-if="col.name == 'id'"></div>
<div v-else>{{ col.label }}</div>
</q-th>
@ -26,18 +44,43 @@
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn unelevated dense size="xs" icon="launch" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.sp_id)">
<q-btn
unelevated
dense
size="xs"
icon="launch"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.sp_id)"
>
<q-tooltip> Jukebox QR </q-tooltip>
</q-btn>
</q-td>
<q-td auto-width>
<q-btn flat dense size="xs" @click="updateJukebox(props.row.id)" icon="edit" color="light-blue"></q-btn>
<q-btn flat dense size="xs" @click="deleteJukebox(props.row.id)" icon="cancel" color="pink">
<q-btn
flat
dense
size="xs"
@click="updateJukebox(props.row.id)"
icon="edit"
color="light-blue"
></q-btn>
<q-btn
flat
dense
size="xs"
@click="deleteJukebox(props.row.id)"
icon="cancel"
color="pink"
>
<q-tooltip> Delete Jukebox </q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props" auto-width>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
auto-width
>
<div v-if="col.name == 'id'"></div>
<div v-else>{{ col.value }}</div>
</q-td>
@ -63,23 +106,62 @@
<q-dialog v-model="jukeboxDialog.show" position="top" @hide="closeFormDialog">
<q-card class="q-pa-md q-pt-lg q-mt-md" style="width: 100%">
<q-stepper v-model="step" active-color="green-7" inactive-color="green-10" vertical animated>
<q-step :name="1" title="Pick wallet, price" icon="account_balance_wallet" :done="step > 1">
<q-input filled class="q-pt-md" dense v-model.trim="jukeboxDialog.data.title" label="Jukebox name"></q-input>
<q-select class="q-pb-md q-pt-md" filled dense emit-value v-model="jukeboxDialog.data.wallet"
:options="g.user.walletOptions" label="Wallet to use"></q-select>
<q-input filled dense v-model.trim="jukeboxDialog.data.price" type="number" max="1440" label="Price per track"
class="q-pb-lg">
<q-stepper
v-model="step"
active-color="green-7"
inactive-color="green-10"
vertical
animated
>
<q-step
:name="1"
title="Pick wallet, price"
icon="account_balance_wallet"
:done="step > 1"
>
<q-input
filled
class="q-pt-md"
dense
v-model.trim="jukeboxDialog.data.title"
label="Jukebox name"
></q-input>
<q-select
class="q-pb-md q-pt-md"
filled
dense
emit-value
v-model="jukeboxDialog.data.wallet"
:options="g.user.walletOptions"
label="Wallet to use"
></q-select>
<q-input
filled
dense
v-model.trim="jukeboxDialog.data.price"
type="number"
max="1440"
label="Price per track"
class="q-pb-lg"
>
</q-input>
<div class="row">
<div class="col-4">
<q-btn
v-if="jukeboxDialog.data.title != null && jukeboxDialog.data.price != null && jukeboxDialog.data.wallet != null"
color="green-7" @click="step = 2">Continue</q-btn>
color="green-7"
@click="step = 2"
>Continue</q-btn
>
<q-btn v-else color="green-7" disable>Continue</q-btn>
</div>
<div class="col-8">
<q-btn color="green-7" class="float-right" @click="closeFormDialog">Cancel</q-btn>
<q-btn
color="green-7"
class="float-right"
@click="closeFormDialog"
>Cancel</q-btn
>
</div>
</div>
@ -90,26 +172,57 @@
<img src="/jukebox/static/spotapi.gif" />
To use this extension you need a Spotify client ID and client secret.
You get these by creating an app in the Spotify developers dashboard
<a target="_blank" style="color:#43a047" href="https://developer.spotify.com/dashboard/applications">here</a>.
<q-input filled class="q-pb-md q-pt-md" dense v-model.trim="jukeboxDialog.data.sp_user" label="Client ID">
<a
target="_blank"
style="color: #43a047"
href="https://developer.spotify.com/dashboard/applications"
>here</a
>.
<q-input
filled
class="q-pb-md q-pt-md"
dense
v-model.trim="jukeboxDialog.data.sp_user"
label="Client ID"
>
</q-input>
<q-input dense v-model="jukeboxDialog.data.sp_secret" filled :type="isPwd ? 'password' : 'text'"
label="Client secret">
<q-input
dense
v-model="jukeboxDialog.data.sp_secret"
filled
:type="isPwd ? 'password' : 'text'"
label="Client secret"
>
<template #append>
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer" @click="isPwd = !isPwd">
<q-icon
:name="isPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="isPwd = !isPwd"
>
</q-icon>
</template>
</q-input>
<div class="row q-mt-md">
<div class="col-4">
<q-btn v-if="jukeboxDialog.data.sp_secret != null && jukeboxDialog.data.sp_user != null && tokenFetched"
color="green-7" @click="submitSpotifyKeys">Submit keys</q-btn>
<q-btn v-else color="green-7" disable color="green-7">Submit keys</q-btn>
<q-btn
v-if="jukeboxDialog.data.sp_secret != null && jukeboxDialog.data.sp_user != null && tokenFetched"
color="green-7"
@click="submitSpotifyKeys"
>Submit keys</q-btn
>
<q-btn v-else color="green-7" disable color="green-7"
>Submit keys</q-btn
>
</div>
<div class="col-8">
<q-btn color="green-7" class="float-right" @click="closeFormDialog">Cancel</q-btn>
<q-btn
color="green-7"
class="float-right"
@click="closeFormDialog"
>Cancel</q-btn
>
</div>
</div>
@ -120,42 +233,93 @@
<img src="/jukebox/static/spotapi1.gif" />
In the app go to edit-settings, set the redirect URI to this link
<br />
<q-btn dense outline unelevated color="green-7" size="xs"
@click="copyText(locationcb + jukeboxDialog.data.sp_id, 'Link copied to clipboard!')">{% raw %}{{ locationcb
}}{{ jukeboxDialog.data.sp_id }}{% endraw
<q-btn
dense
outline
unelevated
color="green-7"
size="xs"
@click="copyText(locationcb + jukeboxDialog.data.sp_id, 'Link copied to clipboard!')"
>{% raw %}{{ locationcb }}{{ jukeboxDialog.data.sp_id }}{% endraw
%}<q-tooltip> Click to copy URL </q-tooltip>
</q-btn>
<br />
Settings can be found
<a target="_blank" style="color:#43a047" href="https://developer.spotify.com/dashboard/applications">here</a>.
<a
target="_blank"
style="color: #43a047"
href="https://developer.spotify.com/dashboard/applications"
>here</a
>.
<div class="row q-mt-md">
<div class="col-4">
<q-btn v-if="jukeboxDialog.data.sp_secret != null && jukeboxDialog.data.sp_user != null && tokenFetched"
color="green-7" @click="authAccess">Authorise access</q-btn>
<q-btn v-else color="green-7" disable color="green-7">Authorise access</q-btn>
<q-btn
v-if="jukeboxDialog.data.sp_secret != null && jukeboxDialog.data.sp_user != null && tokenFetched"
color="green-7"
@click="authAccess"
>Authorise access</q-btn
>
<q-btn v-else color="green-7" disable color="green-7"
>Authorise access</q-btn
>
</div>
<div class="col-8">
<q-btn color="green-7" class="float-right" @click="closeFormDialog">Cancel</q-btn>
<q-btn
color="green-7"
class="float-right"
@click="closeFormDialog"
>Cancel</q-btn
>
</div>
</div>
<br />
</q-step>
<q-step :name="4" title="Select playlists" icon="queue_music" active-color="green-8" :done="step > 4">
<q-select class="q-pb-md q-pt-md" filled dense emit-value v-model="jukeboxDialog.data.sp_device"
:options="devices" label="Device jukebox will play to"></q-select>
<q-select class="q-pb-md" filled dense multiple emit-value v-model="jukeboxDialog.data.sp_playlists"
:options="playlists" label="Playlists available to the jukebox"></q-select>
<q-step
:name="4"
title="Select playlists"
icon="queue_music"
active-color="green-8"
:done="step > 4"
>
<q-select
class="q-pb-md q-pt-md"
filled
dense
emit-value
v-model="jukeboxDialog.data.sp_device"
:options="devices"
label="Device jukebox will play to"
></q-select>
<q-select
class="q-pb-md"
filled
dense
multiple
emit-value
v-model="jukeboxDialog.data.sp_playlists"
:options="playlists"
label="Playlists available to the jukebox"
></q-select>
<div class="row q-mt-md">
<div class="col-5">
<q-btn v-if="jukeboxDialog.data.sp_device != null && jukeboxDialog.data.sp_playlists != null"
color="green-7" @click="createJukebox">Create Jukebox</q-btn>
<q-btn
v-if="jukeboxDialog.data.sp_device != null && jukeboxDialog.data.sp_playlists != null"
color="green-7"
@click="createJukebox"
>Create Jukebox</q-btn
>
<q-btn v-else color="green-7" disable>Create Jukebox</q-btn>
</div>
<div class="col-7">
<q-btn color="green-7" class="float-right" @click="closeFormDialog">Cancel</q-btn>
<q-btn
color="green-7"
class="float-right"
@click="closeFormDialog"
>Cancel</q-btn
>
</div>
</div>
</q-step>
@ -169,15 +333,28 @@
<h5 class="q-my-none">Shareable Jukebox QR</h5>
</center>
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
<qrcode :value="qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id" :options="{width: 800}"
class="rounded-borders"></qrcode>
<qrcode
:value="qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<div class="row q-mt-lg q-gutter-sm">
<q-btn outline color="grey"
@click="copyText(qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id, 'Link copied to clipboard!')">
Copy jukebox link</q-btn>
<q-btn outline color="grey" type="a" :href="qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id"
target="_blank">Open jukebox</q-btn>
<q-btn
outline
color="grey"
@click="copyText(qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id, 'Link copied to clipboard!')"
>
Copy jukebox link</q-btn
>
<q-btn
outline
color="grey"
type="a"
:href="qrCodeDialog.data.url + '/jukebox/' + qrCodeDialog.data.id"
target="_blank"
>Open jukebox</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
</div>
</q-card>
@ -186,4 +363,4 @@
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script src="https://cdn.jsdelivr.net/npm/pica@6.1.1/dist/pica.min.js"></script>
<script src="/jukebox/static/js/index.js"></script>
{% endblock %}
{% endblock %}

View File

@ -9,7 +9,8 @@
<img style="width: 100px" :src="currentPlay.image" />
</div>
<div class="col-8">
<strong style="font-size: 20px">{{ currentPlay.name }}</strong><br />
<strong style="font-size: 20px">{{ currentPlay.name }}</strong
><br />
<strong style="font-size: 15px">{{ currentPlay.artist }}</strong>
</div>
</div>
@ -19,15 +20,30 @@
<q-card class="q-mt-lg">
<q-card-section>
<p style="font-size: 22px">Pick a song</p>
<q-select outlined v-model="playlist" :options="playlists" label="playlists" @input="selectPlaylist()">
<q-select
outlined
v-model="playlist"
:options="playlists"
label="playlists"
@input="selectPlaylist()"
>
</q-select>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<q-virtual-scroll style="max-height: 300px" :items="currentPlaylist" separator>
<q-virtual-scroll
style="max-height: 300px"
:items="currentPlaylist"
separator
>
<template v-slot="{ item, index }">
<q-item :key="index" dense clickable v-ripple
@click="payForSong(item.id, item.name, item.artist, item.image)">
<q-item
:key="index"
dense
clickable
v-ripple
@click="payForSong(item.id, item.name, item.artist, item.image)"
>
<q-item-section>
<q-item-label>
{{ item.name }} - ({{ item.artist }})
@ -55,7 +71,8 @@
</q-card-section>
<br />
<div class="row q-mt-lg q-gutter-sm">
<q-btn outline color="grey" @click="getInvoice(receive.id)">Play for {% endraw %}{{ price }}{% raw %} sats
<q-btn outline color="grey" @click="getInvoice(receive.id)"
>Play for {% endraw %}{{ price }}{% raw %} sats
</q-btn>
</div>
</q-card>
@ -63,10 +80,16 @@
<q-dialog v-model="receive.dialogues.second" position="top">
<q-card class="q-pa-lg lnbits__dialog-card">
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
<qrcode :value="'lightning:' + receive.paymentReq" :options="{width: 800}" class="rounded-borders"></qrcode>
<qrcode
:value="'lightning:' + receive.paymentReq"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<div class="row q-mt-lg q-gutter-sm">
<q-btn outline color="grey" @click="copyText(receive.paymentReq)">Copy invoice</q-btn>
<q-btn outline color="grey" @click="copyText(receive.paymentReq)"
>Copy invoice</q-btn
>
</div>
</q-card>
</q-dialog>
@ -84,7 +107,7 @@
return {
currentPlaylist: [],
currentlyPlaying: {},
cancelListener: () => { },
cancelListener: () => {},
playlists: {},
playlist: '',
heavyList: [],
@ -118,7 +141,7 @@
this.paymentDialog.dismissMsg()
}
},
closeReceiveDialog() { },
closeReceiveDialog() {},
payForSong(song_id, name, artist, image) {
self = this
self.receive.name = name
@ -133,12 +156,11 @@
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/invoice/' +
'{{ juke_id }}' +
'/' +
song_id
'{{ juke_id }}' +
'/' +
song_id
)
.then(function (response) {
self.receive.paymentReq = response.data[0][1]
self.receive.paymentHash = response.data[0][0]
self.receive.dialogues.second = true
@ -153,21 +175,27 @@
self.receive.dialogues.first = false
self.receive.dialogues.second = false
self.$q.notify({
message:
'Processing',
message: 'Processing'
})
LNbits.api
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/invoicep/' + song_id + '/{{ juke_id }}/' + self.receive.paymentHash)
'/jukebox/api/v1/jukebox/jb/invoicep/' +
song_id +
'/{{ juke_id }}/' +
self.receive.paymentHash
)
.then(function (response1) {
if (response1.data[2] == song_id) {
setTimeout(function () { self.getCurrent() }, 500)
setTimeout(function () {
self.getCurrent()
}, 500)
self.$q.notify({
color: 'green',
message:
'Success! "' + self.receive.name + '" will be played soon',
'Success! "' +
self.receive.name +
'" will be played soon',
timeout: 3000
})
@ -176,17 +204,14 @@
}
})
.catch(err => {
LNbits.utils.notifyApiError(err)
self.paid = false
response1 = []
})
}
}, 3000)
})
.catch(err => {
self.$q.notify({
color: 'warning',
html: true,
@ -197,16 +222,17 @@
})
},
checkInvoice(juke_id, paymentHash) {
var self = this
LNbits.api
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/checkinvoice/' + juke_id + '/' + paymentHash,
'/jukebox/api/v1/jukebox/jb/checkinvoice/' +
juke_id +
'/' +
paymentHash,
'filla'
)
.then(function (response) {
self.paid = response.data.paid
})
.catch(function (error) {
@ -214,21 +240,16 @@
})
},
getCurrent() {
LNbits.api
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/currently/{{juke_id}}')
.request('GET', '/jukebox/api/v1/jukebox/jb/currently/{{juke_id}}')
.then(function (res) {
if (res.data.id) {
self.currentlyPlaying = res.data
}
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
selectPlaylist() {
self = this
@ -236,9 +257,9 @@
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/playlist/' +
'{{ juke_id }}' +
'/' +
self.playlist.split(',')[0].split('-')[1]
'{{ juke_id }}' +
'/' +
self.playlist.split(',')[0].split('-')[1]
)
.then(function (response) {
self.currentPlaylist = response.data
@ -247,7 +268,7 @@
LNbits.utils.notifyApiError(err)
})
},
currentSong() { }
currentSong() {}
},
created() {
this.getCurrent()
@ -258,9 +279,9 @@
.request(
'GET',
'/jukebox/api/v1/jukebox/jb/playlist/' +
'{{ juke_id }}' +
'/' +
self.playlists[0].split(',')[0].split('-')[1]
'{{ juke_id }}' +
'/' +
self.playlists[0].split(',')[0].split('-')[1]
)
.then(function (response) {
self.currentPlaylist = response.data
@ -273,4 +294,4 @@
}
})
</script>
{% endblock %}
{% endblock %}

View File

@ -214,7 +214,7 @@
</div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script>
var mapUserManager = function(obj) {
var mapUserManager = function (obj) {
obj.date = Quasar.utils.date.formatDate(
new Date(obj.time * 1000),
'YYYY-MM-DD HH:mm'
@ -228,7 +228,7 @@
new Vue({
el: '#vue',
mixins: [windowMixin],
data: function() {
data: function () {
return {
wallets: [],
users: [],
@ -277,8 +277,8 @@
}
},
computed: {
userOptions: function() {
return this.users.map(function(obj) {
userOptions: function () {
return this.users.map(function (obj) {
console.log(obj.id)
return {
value: String(obj.id),
@ -290,7 +290,7 @@
methods: {
///////////////Users////////////////////////////
getUsers: function() {
getUsers: function () {
var self = this
LNbits.api
@ -299,20 +299,20 @@
'/usermanager/api/v1/users',
this.g.user.wallets[0].inkey
)
.then(function(response) {
self.users = response.data.map(function(obj) {
.then(function (response) {
self.users = response.data.map(function (obj) {
return mapUserManager(obj)
})
})
},
openUserUpdateDialog: function(linkId) {
openUserUpdateDialog: function (linkId) {
var link = _.findWhere(this.users, {id: linkId})
this.userDialog.data = _.clone(link._data)
this.userDialog.show = true
},
sendUserFormData: function() {
sendUserFormData: function () {
if (this.userDialog.data.id) {
} else {
var data = {
@ -329,7 +329,7 @@
}
},
createUser: function(data) {
createUser: function (data) {
var self = this
LNbits.api
.request(
@ -338,48 +338,48 @@
this.g.user.wallets[0].inkey,
data
)
.then(function(response) {
.then(function (response) {
self.users.push(mapUserManager(response.data))
self.userDialog.show = false
self.userDialog.data = {}
data = {}
self.getWallets()
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
deleteUser: function(userId) {
deleteUser: function (userId) {
var self = this
console.log(userId)
LNbits.utils
.confirmDialog('Are you sure you want to delete this User link?')
.onOk(function() {
.onOk(function () {
LNbits.api
.request(
'DELETE',
'/usermanager/api/v1/users/' + userId,
self.g.user.wallets[0].inkey
)
.then(function(response) {
self.users = _.reject(self.users, function(obj) {
.then(function (response) {
self.users = _.reject(self.users, function (obj) {
return obj.id == userId
})
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
})
},
exportUsersCSV: function() {
exportUsersCSV: function () {
LNbits.utils.exportCSV(this.usersTable.columns, this.users)
},
///////////////Wallets////////////////////////////
getWallets: function() {
getWallets: function () {
var self = this
LNbits.api
@ -388,19 +388,19 @@
'/usermanager/api/v1/wallets',
this.g.user.wallets[0].inkey
)
.then(function(response) {
self.wallets = response.data.map(function(obj) {
.then(function (response) {
self.wallets = response.data.map(function (obj) {
return mapUserManager(obj)
})
})
},
openWalletUpdateDialog: function(linkId) {
openWalletUpdateDialog: function (linkId) {
var link = _.findWhere(this.users, {id: linkId})
this.walletDialog.data = _.clone(link._data)
this.walletDialog.show = true
},
sendWalletFormData: function() {
sendWalletFormData: function () {
if (this.walletDialog.data.id) {
} else {
var data = {
@ -415,7 +415,7 @@
}
},
createWallet: function(data) {
createWallet: function (data) {
var self = this
LNbits.api
.request(
@ -424,43 +424,43 @@
this.g.user.wallets[0].inkey,
data
)
.then(function(response) {
.then(function (response) {
self.wallets.push(mapUserManager(response.data))
self.walletDialog.show = false
self.walletDialog.data = {}
data = {}
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
deleteWallet: function(userId) {
deleteWallet: function (userId) {
var self = this
LNbits.utils
.confirmDialog('Are you sure you want to delete this wallet link?')
.onOk(function() {
.onOk(function () {
LNbits.api
.request(
'DELETE',
'/usermanager/api/v1/wallets/' + userId,
self.g.user.wallets[0].inkey
)
.then(function(response) {
self.wallets = _.reject(self.wallets, function(obj) {
.then(function (response) {
self.wallets = _.reject(self.wallets, function (obj) {
return obj.id == userId
})
})
.catch(function(error) {
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
})
},
exportWalletsCSV: function() {
exportWalletsCSV: function () {
LNbits.utils.exportCSV(this.walletsTable.columns, this.wallets)
}
},
created: function() {
created: function () {
if (this.g.user.wallets.length) {
this.getUsers()
this.getWallets()