Merge branch 'master' into StreamerCopilot

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

View file

@ -93,7 +93,11 @@ new Vue({
getJukeboxes() { getJukeboxes() {
self = this self = this
LNbits.api 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) { .then(function (response) {
self.JukeboxLinks = response.data.map(mapJukebox) self.JukeboxLinks = response.data.map(mapJukebox)
}) })
@ -195,9 +199,9 @@ new Vue({
if (self.jukeboxDialog.data.sp_access_token) { if (self.jukeboxDialog.data.sp_access_token) {
self.refreshPlaylists() self.refreshPlaylists()
self.refreshDevices() self.refreshDevices()
console.log("this.devices") console.log('this.devices')
console.log(self.devices) console.log(self.devices)
console.log("this.devices") console.log('this.devices')
setTimeout(function () { setTimeout(function () {
if (self.devices.length < 1 || self.playlists.length < 1) { if (self.devices.length < 1 || self.playlists.length < 1) {
self.$q.notify({ self.$q.notify({

View file

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

View file

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

View file

@ -12,7 +12,9 @@
style="font-size: 20rem" style="font-size: 20rem"
></q-icon> ></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 /> <br />
</center> </center>
</q-card-section> </q-card-section>

View file

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

View file

@ -9,7 +9,8 @@
<img style="width: 100px" :src="currentPlay.image" /> <img style="width: 100px" :src="currentPlay.image" />
</div> </div>
<div class="col-8"> <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> <strong style="font-size: 15px">{{ currentPlay.artist }}</strong>
</div> </div>
</div> </div>
@ -19,15 +20,30 @@
<q-card class="q-mt-lg"> <q-card class="q-mt-lg">
<q-card-section> <q-card-section>
<p style="font-size: 22px">Pick a song</p> <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-select>
</q-card-section> </q-card-section>
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<q-separator></q-separator> <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 }"> <template v-slot="{ item, index }">
<q-item :key="index" dense clickable v-ripple <q-item
@click="payForSong(item.id, item.name, item.artist, item.image)"> :key="index"
dense
clickable
v-ripple
@click="payForSong(item.id, item.name, item.artist, item.image)"
>
<q-item-section> <q-item-section>
<q-item-label> <q-item-label>
{{ item.name }} - ({{ item.artist }}) {{ item.name }} - ({{ item.artist }})
@ -55,7 +71,8 @@
</q-card-section> </q-card-section>
<br /> <br />
<div class="row q-mt-lg q-gutter-sm"> <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> </q-btn>
</div> </div>
</q-card> </q-card>
@ -63,10 +80,16 @@
<q-dialog v-model="receive.dialogues.second" position="top"> <q-dialog v-model="receive.dialogues.second" position="top">
<q-card class="q-pa-lg lnbits__dialog-card"> <q-card class="q-pa-lg lnbits__dialog-card">
<q-responsive :ratio="1" class="q-mx-xl q-mb-md"> <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> </q-responsive>
<div class="row q-mt-lg q-gutter-sm"> <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> </div>
</q-card> </q-card>
</q-dialog> </q-dialog>
@ -138,7 +161,6 @@
song_id song_id
) )
.then(function (response) { .then(function (response) {
self.receive.paymentReq = response.data[0][1] self.receive.paymentReq = response.data[0][1]
self.receive.paymentHash = response.data[0][0] self.receive.paymentHash = response.data[0][0]
self.receive.dialogues.second = true self.receive.dialogues.second = true
@ -153,21 +175,27 @@
self.receive.dialogues.first = false self.receive.dialogues.first = false
self.receive.dialogues.second = false self.receive.dialogues.second = false
self.$q.notify({ self.$q.notify({
message: message: 'Processing'
'Processing',
}) })
LNbits.api LNbits.api
.request( .request(
'GET', '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) { .then(function (response1) {
if (response1.data[2] == song_id) { if (response1.data[2] == song_id) {
setTimeout(function () { self.getCurrent() }, 500) setTimeout(function () {
self.getCurrent()
}, 500)
self.$q.notify({ self.$q.notify({
color: 'green', color: 'green',
message: message:
'Success! "' + self.receive.name + '" will be played soon', 'Success! "' +
self.receive.name +
'" will be played soon',
timeout: 3000 timeout: 3000
}) })
@ -176,17 +204,14 @@
} }
}) })
.catch(err => { .catch(err => {
LNbits.utils.notifyApiError(err) LNbits.utils.notifyApiError(err)
self.paid = false self.paid = false
response1 = [] response1 = []
}) })
} }
}, 3000) }, 3000)
}) })
.catch(err => { .catch(err => {
self.$q.notify({ self.$q.notify({
color: 'warning', color: 'warning',
html: true, html: true,
@ -197,16 +222,17 @@
}) })
}, },
checkInvoice(juke_id, paymentHash) { checkInvoice(juke_id, paymentHash) {
var self = this var self = this
LNbits.api LNbits.api
.request( .request(
'GET', 'GET',
'/jukebox/api/v1/jukebox/jb/checkinvoice/' + juke_id + '/' + paymentHash, '/jukebox/api/v1/jukebox/jb/checkinvoice/' +
juke_id +
'/' +
paymentHash,
'filla' 'filla'
) )
.then(function (response) { .then(function (response) {
self.paid = response.data.paid self.paid = response.data.paid
}) })
.catch(function (error) { .catch(function (error) {
@ -214,21 +240,16 @@
}) })
}, },
getCurrent() { getCurrent() {
LNbits.api LNbits.api
.request( .request('GET', '/jukebox/api/v1/jukebox/jb/currently/{{juke_id}}')
'GET',
'/jukebox/api/v1/jukebox/jb/currently/{{juke_id}}')
.then(function (res) { .then(function (res) {
if (res.data.id) { if (res.data.id) {
self.currentlyPlaying = res.data self.currentlyPlaying = res.data
} }
}) })
.catch(function (error) { .catch(function (error) {
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
}) })
}, },
selectPlaylist() { selectPlaylist() {
self = this self = this