Compare commits

...
Author SHA1 Message Date
Tiago Vasconcelos 9a9e638c1e fix: separate concerns 2026-03-19 11:13:32 +00:00
Tiago Vasconcelos 59a2fefbf3 chore: lint & bundle 2026-03-19 09:59:17 +00:00
Tiago Vasconcelos 4725eb95c9 users page dialogs 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos a5aaced420 node page dialogs 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 87a6514b62 some extensions dialogs
some need a bit more work
2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 32c893027d audit detail dialog 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 751598e0f8 remove margin in title 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos e11ccd9757 account dialogs 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 7e344de10e funding sources qr 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 08fdeedffc exchange ticker dialog 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 73ba9d94a5 wallet icon dialog 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 1640e23f75 new wallet dialog 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 9145c13435 qr scanner dialog 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos 41048b8cc7 icon prop takes real estate 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos b46e2c549d hodl invoice 2026-03-19 09:54:27 +00:00
Tiago Vasconcelos b382ccfdf3 add optional secondary action button 2026-03-19 09:53:22 +00:00
Tiago Vasconcelos 1687972d89 payment details 2026-03-19 09:53:22 +00:00
Tiago Vasconcelos d621a6f81f . 2026-03-19 09:48:45 +00:00
Tiago Vasconcelos b9d00d900e prettier 2026-03-19 09:48:45 +00:00
Tiago Vasconcelos 0f06b7ba52 chore: bundle 2026-03-19 09:48:45 +00:00
Tiago Vasconcelos 220ece6027 fix mixed bindings 2026-03-19 09:47:57 +00:00
Tiago Vasconcelos 1663845468 remove action slot 2026-03-19 09:47:57 +00:00
Tiago Vasconcelos 5b7d1e63b5 test fixes 2026-03-19 09:47:57 +00:00
Tiago Vasconcelos 5bd8bf2f56 init 2026-03-19 09:47:57 +00:00
17 changed files with 905 additions and 908 deletions
File diff suppressed because one or more lines are too long
@@ -0,0 +1,105 @@
window.app.component('lnbits-dialog', {
template: '#lnbits-dialog',
props: {
show: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
position: {
type: String,
default: 'top'
},
persistent: {
type: Boolean,
default: false
},
showCancel: {
type: Boolean,
default: true
},
cancelLabel: {
type: String,
default: 'Close'
},
cancelColor: {
type: String,
default: 'grey'
},
action: {
type: Object,
default: null
},
secondaryAction: {
type: Object,
default: null
}
},
emits: ['update:show', 'hide', 'cancel', 'action', 'secondary-action'],
computed: {
hasAction() {
return !!(this.action && this.action.label)
},
hasSecondaryAction() {
return !!(this.secondaryAction && this.secondaryAction.label)
},
actionProps() {
const action = this.action || {}
const obj = {
label: action.label || 'Action',
color: action.color || 'primary',
loading: !!action.loading,
disable: !!action.disable,
closePopup: !!action.closePopup
}
if (action.icon) {
obj.icon = action.icon
}
return obj
},
secondaryActionProps() {
const action = this.secondaryAction || {}
const obj = {
label: action.label || 'Secondary',
color: action.color || 'secondary',
loading: !!action.loading,
disable: !!action.disable,
closePopup: !!action.closePopup
}
if (action.icon) {
obj.icon = action.icon
}
return obj
}
},
methods: {
handleModelUpdate(value) {
this.$emit('update:show', value)
},
handleHide() {
this.handleModelUpdate(false)
this.$emit('hide')
},
handleCancel() {
this.$emit('cancel')
},
handleAction() {
this.$emit('action')
},
handleSecondaryAction() {
this.$emit('secondary-action')
}
}
})
+1
View File
@@ -70,6 +70,7 @@
"js/components/admin/lnbits-admin-site-customisation.js", "js/components/admin/lnbits-admin-site-customisation.js",
"js/components/admin/lnbits-admin-assets-config.js", "js/components/admin/lnbits-admin-assets-config.js",
"js/components/admin/lnbits-admin-audit.js", "js/components/admin/lnbits-admin-audit.js",
"js/components/lnbits-dialog.js",
"js/components/lnbits-wallet-charts.js", "js/components/lnbits-wallet-charts.js",
"js/components/lnbits-wallet-api-docs.js", "js/components/lnbits-wallet-api-docs.js",
"js/components/lnbits-wallet-icon.js", "js/components/lnbits-wallet-icon.js",
+2 -1
View File
@@ -30,7 +30,8 @@ include('components/lnbits-wallet-share.vue') %} {%
include('components/lnbits-wallet-charts.vue') %} {% include('components/lnbits-wallet-charts.vue') %} {%
include('components/lnbits-wallet-paylinks.vue') %} {% include('components/lnbits-wallet-paylinks.vue') %} {%
include('components/lnbits-wallet-extra.vue') %} {% include('components/lnbits-wallet-extra.vue') %} {%
include('components/lnbits-error.vue') %} include('components/lnbits-error.vue') %} {%
include('components/lnbits-dialog.vue') %}
<template id="lnbits-manage"> <template id="lnbits-manage">
<q-list v-if="g.user" dense class="lnbits-drawer__q-list"> <q-list v-if="g.user" dense class="lnbits-drawer__q-list">
@@ -199,47 +199,36 @@
</div> </div>
<div class="col-md-8 col-sm-12"></div> <div class="col-md-8 col-sm-12"></div>
</div> </div>
<lnbits-dialog
<q-dialog v-model="exchangeData.showTickerConversion" position="top"> :show="exchangeData.showTickerConversion"
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> :title="$t('create_ticker_converter')"
<div class="q-mb-md"> :action="{
<strong v-text="$t('create_ticker_converter')"></strong> label: 'Add Ticker Conversion'
}"
:cancel-label="$t('close')"
@update:show="exchangeData.showTickerConversion = $event"
@action="addExchangeTickerConversion()"
>
<div class="row">
<div class="col-12 q-mb-md">
<q-select
filled
dense
v-model="exchangeData.convertFromTicker"
label="From Currency"
:options="currencies"
></q-select>
</div> </div>
<div class="row"> <div class="col-12">
<div class="col-12 q-mb-md"> <q-input
<q-select v-model="exchangeData.convertToTicker"
filled dense
dense filled
v-model="exchangeData.convertFromTicker" label="New Ticker"
label="From Currency" hint="This ticker will be used for the exchange API calls."
:options="currencies" >
></q-select> </q-input>
</div>
<div class="col-12">
<q-input
v-model="exchangeData.convertToTicker"
dense
filled
label="New Ticker"
hint="This ticker will be used for the exchange API calls."
>
</q-input>
</div>
</div> </div>
<div class="row q-mt-lg"> </div>
<q-btn </lnbits-dialog>
@click="addExchangeTickerConversion()"
label="Add Ticker Conversion"
color="primary"
></q-btn>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('close')"
></q-btn>
</div>
</q-card>
</q-dialog>
</template> </template>
@@ -125,15 +125,14 @@
</q-expansion-item> </q-expansion-item>
</div> </div>
</q-list> </q-list>
<q-dialog v-model="showQRDialog"> <lnbits-dialog
<q-card class="q-pa-md"> :show="showQRDialog"
<q-card-section> :position="'standard'"
<lnbits-qrcode :value="qrValue"></lnbits-qrcode> @update:show="showQRDialog = $event"
</q-card-section> >
<q-card-actions align="right"> <q-card-section>
<q-btn flat :label="$t('close')" v-close-popup /> <lnbits-qrcode :value="qrValue"></lnbits-qrcode>
</q-card-actions> </q-card-section>
</q-card> </lnbits-dialog>
</q-dialog>
</div> </div>
</template> </template>
@@ -0,0 +1,61 @@
<template id="lnbits-dialog">
<q-dialog
:model-value="show"
:position="position"
:persistent="persistent"
@update:model-value="handleModelUpdate"
@hide="handleHide"
>
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
<!-- Header with optional title -->
<q-card-section v-if="title">
<div class="text-h6" v-text="title"></div>
</q-card-section>
<!-- Main content slot -->
<q-card-section>
<slot></slot>
</q-card-section>
<q-card-actions
v-if="showCancel || hasAction || hasSecondaryAction"
class="q-mt-lg"
align="right"
>
<q-btn
v-if="showCancel"
v-close-popup
flat
:color="cancelColor"
:label="cancelLabel"
@click="handleCancel"
></q-btn>
<q-space></q-space>
<q-btn
v-if="hasSecondaryAction"
:icon="secondaryActionProps.icon"
:color="secondaryActionProps.color"
:label="secondaryActionProps.label"
:loading="secondaryActionProps.loading"
:disable="secondaryActionProps.disable"
@click="handleSecondaryAction"
v-close-popup="secondaryActionProps.closePopup"
class="q-mr-sm"
></q-btn>
<q-btn
v-if="hasAction"
:icon="actionProps.icon"
:color="actionProps.color"
:label="actionProps.label"
:loading="actionProps.loading"
:disable="actionProps.disable"
@click="handleAction"
v-close-popup="actionProps.closePopup"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
</template>
@@ -394,159 +394,135 @@
></span> ></span>
</i> </i>
</q-td> </q-td>
<q-dialog v-model="props.expand" :props="props" position="top"> <lnbits-dialog
<q-card class="q-pa-sm q-pt-xl lnbits__dialog-card"> :show="props.expand"
<q-card-section> :cancel-label="$t('close')"
<q-list bordered separator> :action="{
<q-expansion-item label: $t('check_payment'),
expand-separator icon: 'refresh'
:default-opened="!(props.row.isIn && props.row.isPending)" }"
> @update:show="props.expand = $event"
<template v-slot:header> @action="checkPayment(props.row.payment_hash)"
<q-item-section avatar> >
<q-icon <q-list bordered separator>
:color=" <q-expansion-item
props.row.isPaid && props.row.isIn expand-separator
? 'green' :default-opened="!(props.row.isIn && props.row.isPending)"
: props.row.isPaid && props.row.isOut >
? 'pink' <template v-slot:header>
: props.row.isFailed <q-item-section avatar>
? 'yellow' <q-icon
: 'grey' :color="
" props.row.isPaid && props.row.isIn
:name=" ? 'green'
props.row.isPaid && props.row.isIn : props.row.isPaid && props.row.isOut
? 'call_received' ? 'pink'
: props.row.isPaid && props.row.isOut : props.row.isFailed
? 'call_made' ? 'yellow'
: props.row.isFailed : 'grey'
? 'warning' "
: 'settings_ethernet' :name="
" props.row.isPaid && props.row.isIn
/> ? 'call_received'
</q-item-section> : props.row.isPaid && props.row.isOut
? 'call_made'
: props.row.isFailed
? 'warning'
: 'settings_ethernet'
"
/>
</q-item-section>
<q-item-section> <q-item-section>
<q-item-label <q-item-label
v-text=" v-text="
props.row.isIn && props.row.isPending props.row.isIn && props.row.isPending
? $t('invoice_waiting') ? $t('invoice_waiting')
: props.row.isOut && props.row.isPending : props.row.isOut && props.row.isPending
? $t('outgoing_payment_pending') ? $t('outgoing_payment_pending')
: props.row.isPaid && props.row.isIn : props.row.isPaid && props.row.isIn
? $t('payment_received') ? $t('payment_received')
: props.row.isPaid && props.row.isOut : props.row.isPaid && props.row.isOut
? $t('payment_sent') ? $t('payment_sent')
: props.row.isFailed : props.row.isFailed
? $t('payment_failed') ? $t('payment_failed')
: '' : ''
" "
></q-item-label> ></q-item-label>
</q-item-section> </q-item-section>
<q-item-section v-if="props.row.tag" side> <q-item-section v-if="props.row.tag" side>
<q-badge <q-badge
v-if="props.row.extra && !!props.row.extra.tag" v-if="props.row.extra && !!props.row.extra.tag"
color="yellow" color="yellow"
text-color="black" text-color="black"
> >
#<span v-text="props.row.tag"></span> #<span v-text="props.row.tag"></span>
</q-badge> </q-badge>
</q-item-section> </q-item-section>
</template> </template>
<q-separator></q-separator> <q-separator></q-separator>
<lnbits-payment-details <lnbits-payment-details
:payment="props.row" :payment="props.row"
></lnbits-payment-details> ></lnbits-payment-details>
</q-expansion-item> </q-expansion-item>
</q-list> </q-list>
<div <div
v-if=" v-if="props.row.isIn && props.row.isPending && props.row.bolt11"
props.row.isIn && props.row.isPending && props.row.bolt11 >
" <div v-if="props.row.extra.fiat_payment_request">
> <lnbits-qrcode
<div v-if="props.row.extra.fiat_payment_request"> :value="props.row.extra.fiat_payment_request"
<lnbits-qrcode :href="props.row.extra.fiat_payment_request"
:value="props.row.extra.fiat_payment_request" :show-buttons="false"
:href="props.row.extra.fiat_payment_request" ></lnbits-qrcode>
:show-buttons="false" </div>
></lnbits-qrcode> <div v-else>
</div> <lnbits-qrcode
<div v-else> :value="'lightning:' + props.row.bolt11.toUpperCase()"
<lnbits-qrcode :href="'lightning:' + props.row.bolt11"
:value="'lightning:' + props.row.bolt11.toUpperCase()" ></lnbits-qrcode>
:href="'lightning:' + props.row.bolt11" </div>
></lnbits-qrcode> </div>
</div> </lnbits-dialog>
</div> <lnbits-dialog
<div class="row q-mt-md"> :show="hodlInvoice.show"
<q-btn :cancel-label="$t('close')"
outline :action="{
color="grey" label: $t('cancel_invoice'),
@click="checkPayment(props.row.payment_hash)" color: 'grey',
icon="refresh" closePopup: true
:label="$t('payment_check')" }"
></q-btn> :secondary-action="{
<q-btn label: $t('settle_invoice'),
v-close-popup color: 'grey',
flat closePopup: true
color="grey" }"
class="q-ml-auto" @update:show="hodlInvoice.show = $event"
:label="$t('close')" @action="cancelHoldInvoice(hodlInvoice.payment.payment_hash)"
></q-btn> @secondary-action="settleHoldInvoice(hodlInvoice.preimage)"
</div> >
</q-card-section> <q-card-section>
</q-card> <q-item-label class="text-h6">
</q-dialog> <span v-text="$t('hold_invoice')"></span>
<q-dialog v-model="hodlInvoice.show" position="top"> </q-item-label>
<q-card class="q-pa-sm q-pt-xl lnbits__dialog-card"> <q-item-label class="text-subtitle2">
<q-card-section> <span v-text="$t('hold_invoice_description')"></span>
<q-item-label class="text-h6"> </q-item-label>
<span v-text="$t('hold_invoice')"></span> </q-card-section>
</q-item-label> <q-card-section>
<q-item-label class="text-subtitle2"> <q-input
<span v-text="$t('hold_invoice_description')"></span> filled
</q-item-label> :label="$t('preimage')"
</q-card-section> :hint="$t('preimage_hint')"
<q-card-section> v-model="hodlInvoice.preimage"
<q-input dense
filled autofocus
:label="$t('preimage')" @keyup.enter="settleHoldInvoice(hodlInvoice.preimage)"
:hint="$t('preimage_hint')" >
v-model="hodlInvoice.preimage" </q-input>
dense </q-card-section>
autofocus </lnbits-dialog>
@keyup.enter="settleHoldInvoice(hodlInvoice.preimage)"
>
</q-input>
</q-card-section>
<q-card-section class="row q-gutter-x-sm">
<q-btn
@click="settleHoldInvoice(hodlInvoice.preimage)"
outline
v-close-popup
color="grey"
:label="$t('settle_invoice')"
>
</q-btn>
<q-btn
v-close-popup
outline
color="grey"
class="q-ml-sm"
@click="cancelHoldInvoice(hodlInvoice.payment.payment_hash)"
:label="$t('cancel_invoice')"
></q-btn>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
:label="$t('close')"
></q-btn>
</q-card-section>
</q-card>
</q-dialog>
</q-tr> </q-tr>
</template> </template>
</q-table> </q-table>
@@ -1,22 +1,16 @@
<template id="lnbits-qrcode-scanner"> <template id="lnbits-qrcode-scanner">
<q-dialog v-model="showScanner" position="top"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-xl"> :show="showScanner"
<div class="text-center q-mb-lg"> :cancel-label="$t('cancel')"
<qrcode-stream @update:show="showScanner = $event"
@detect="detect" @cancel="reset"
@camera-on="onInitQR" >
class="rounded-borders" <div class="text-center q-mb-lg">
></qrcode-stream> <qrcode-stream
</div> @detect="detect"
<div class="row q-mt-lg"> @camera-on="onInitQR"
<q-btn class="rounded-borders"
@click="reset" ></qrcode-stream>
flat </div>
color="grey" </lnbits-dialog>
class="q-ml-auto"
:label="$t('cancel')"
></q-btn>
</div>
</q-card>
</q-dialog>
</template> </template>
@@ -8,49 +8,48 @@
icon="edit" icon="edit"
style="position: relative; left: -15px; bottom: -10px" style="position: relative; left: -15px; bottom: -10px"
></q-btn> ></q-btn>
<q-dialog v-model="icon.show" position="top"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card"> :show="icon.show"
<q-form @submit="setIcon" class="q-gutter-md"> :action="{
<div class="q-gutter-sm q-pa-sm flex flex-wrap justify-center"> label: 'Save Icon',
disable: !icon.data.icon
}"
@update:show="icon.show = $event"
@action="setIcon"
@hide="icon.data = {}"
>
<q-form class="q-gutter-md">
<div class="q-gutter-sm q-pa-sm flex flex-wrap justify-center">
<q-btn
v-for="(thisIcon, index) in icon.options"
:key="index"
@click="setSelectedIcon(thisIcon)"
round
text-color="black"
:color="
icon.data.icon === thisIcon
? icon.data.color || 'primary'
: 'grey-5'
"
size="md"
:icon="thisIcon"
class="q-mb-sm"
></q-btn>
</div>
<div class="q-pa-sm flex justify-between items-center">
<div class="flex q-pl-lg">
<q-btn <q-btn
v-for="(thisIcon, index) in icon.options" v-for="(color, index) in icon.colorOptions"
:key="index" :key="'color-' + index"
@click="setSelectedIcon(thisIcon)" @click="setSelectedColor(color)"
round round
text-color="black" :color="color"
:color=" size="xs"
icon.data.icon === thisIcon style="width: 24px; height: 24px; min-width: 24px; padding: 0"
? icon.data.color || 'primary' class="q-mr-xs"
: 'grey-5'
"
size="md"
:icon="thisIcon"
class="q-mb-sm"
></q-btn> ></q-btn>
</div> </div>
<div class="q-pa-sm flex justify-between items-center"> </div>
<div class="flex q-pl-lg"> </q-form>
<q-btn </lnbits-dialog>
v-for="(color, index) in icon.colorOptions"
:key="'color-' + index"
@click="setSelectedColor(color)"
round
:color="color"
size="xs"
style="width: 24px; height: 24px; min-width: 24px; padding: 0"
class="q-mr-xs"
></q-btn>
</div>
<q-btn
unelevated
color="primary"
:disable="!icon.data.icon"
type="submit"
>
Save Icon
</q-btn>
</div>
</q-form>
</q-card>
</q-dialog>
</template> </template>
@@ -1,94 +1,72 @@
<template id="lnbits-wallet-new"> <template id="lnbits-wallet-new">
<q-dialog v-model="showNewWalletDialog" position="top"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-md lnbits__dialog-card"> :show="showNewWalletDialog"
<q-card-section> :title="$t('add_new_wallet')"
<div class="text-h6"> :action="{
<span v-text="$t('add_new_wallet')"></span> label: $t('add_wallet'),
</div> closePopup: true
</q-card-section> }"
<q-card-section v-if="g.user.walletInvitesCount"> :secondary-action="
<q-badge isLightningShared
@click="g.newWalletType = 'lightning-shared'" ? {
class="cursor-pointer" label: $t('reject_wallet'),
> color: 'negative',
<span closePopup: true
v-text=" }
'You have ' + : null
g.user.walletInvitesCount + "
' wallet invitation' + @update:show="showNewWalletDialog = $event"
(g.user.walletInvitesCount > 1 ? 's' : '') @action="submitAddWallet"
" @secondary-action="submitRejectWalletInvitation"
></span> >
</q-badge> <q-card-section v-if="g.user.walletInvitesCount">
</q-card-section> <q-badge
@click="g.newWalletType = 'lightning-shared'"
class="cursor-pointer"
>
<span
v-text="
'You have ' +
g.user.walletInvitesCount +
' wallet invitation' +
(g.user.walletInvitesCount > 1 ? 's' : '')
"
></span>
</q-badge>
</q-card-section>
<q-card-section class="q-pt-none"> <q-card-section class="q-pt-none">
<q-select <q-select
v-if="walletTypes.length > 1" v-if="walletTypes.length > 1"
:options="walletTypes" :options="walletTypes"
emit-value emit-value
map-options map-options
:label="$t('wallet_type')" :label="$t('wallet_type')"
v-model="g.newWalletType" v-model="g.newWalletType"
dense dense
></q-select> ></q-select>
<q-input <q-input
v-if="isLightning" v-if="isLightning"
dense dense
v-model="wallet.name" v-model="wallet.name"
:label="$t('wallet_name')" :label="$t('wallet_name')"
autofocus autofocus
@keyup.enter="submitAddWallet()" @keyup.enter="submitAddWallet()"
class="q-mt-md" class="q-mt-md"
></q-input> ></q-input>
<q-select <q-select
v-if="isLightningShared" v-if="isLightningShared"
v-model="wallet.sharedWalletId" v-model="wallet.sharedWalletId"
:label="$t('shared_wallet_id')" :label="$t('shared_wallet_id')"
emit-value emit-value
map-options map-options
dense dense
:options="inviteWalletOptions" :options="inviteWalletOptions"
class="q-mt-md" class="q-mt-md"
></q-select> ></q-select>
<div v-if="isLightningShared" class="q-mt-md"> <div v-if="isLightningShared" class="q-mt-md">
<span v-text="$t('shared_wallet_desc')" class="q-mt-lg"></span> <span v-text="$t('shared_wallet_desc')" class="q-mt-lg"></span>
</div> </div>
</q-card-section> </q-card-section>
</lnbits-dialog>
<q-card-actions class="text-primary">
<div class="row full-width">
<div class="col-md-4">
<q-btn
flat
:label="$t('cancel')"
class="float-left"
v-close-popup
></q-btn>
</div>
<div class="col-md-4">
<q-btn
v-if="isLightningShared"
:disabled="!wallet.sharedWalletId"
flat
:label="$t('reject_wallet')"
v-close-popup
color="negative"
@click="submitRejectWalletInvitation()"
></q-btn>
<span v-else></span>
</div>
<div class="col-md-4">
<q-btn
flat
:label="$t('add_wallet')"
v-close-popup
@click="submitAddWallet()"
class="float-right"
></q-btn>
</div>
</div>
</q-card-actions>
</q-card>
</q-dialog>
</template> </template>
+161 -200
View File
@@ -1231,213 +1231,174 @@
</div> </div>
</div> </div>
<q-dialog v-model="apiAcl.showPasswordDialog" position="top"> <lnbits-dialog
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> :show="apiAcl.showPasswordDialog"
<strong>User Password</strong> title="Password Required"
<div class="row q-mt-md q-col-gutter-md"> :action="{
<div class="col-12"> label: $t('ok')
<q-input }"
v-model="apiAcl.password" @update:show="apiAcl.showPasswordDialog = $event"
type="password" @action="runPasswordGuardedFunction()"
dense >
filled <div class="row q-col-gutter-md">
label="Password" <div class="col-12">
hint="User password is required for this action." <q-input
> v-model="apiAcl.password"
</q-input> type="password"
</div> dense
filled
label="Password"
hint="User password is required for this action."
>
</q-input>
</div> </div>
<div class="row q-mt-lg"> </div>
<q-btn </lnbits-dialog>
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('cancel')"
></q-btn>
<q-btn
@click="runPasswordGuardedFunction()"
:label="$t('ok')"
color="primary"
></q-btn>
</div>
</q-card>
</q-dialog>
<q-dialog v-model="apiAcl.showNewAclDialog" position="top"> <lnbits-dialog
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> :show="apiAcl.showNewAclDialog"
<strong>New API Access Control List</strong> title="New API Access Control List"
<div class="row q-mt-md q-col-gutter-md"> :action="{
<div class="col-12"> label: 'Create'
<q-input v-model="apiAcl.newAclName" dense filled label="ACL Name"> }"
</q-input> :cancel-label="$t('close')"
</div> @update:show="apiAcl.showNewAclDialog = $event"
@action="addApiACL()"
>
<div class="row q-col-gutter-md">
<div class="col-12">
<q-input v-model="apiAcl.newAclName" dense filled label="ACL Name">
</q-input>
</div> </div>
<div class="row q-mt-lg"> </div>
<q-btn @click="addApiACL()" label="Create" color="primary"></q-btn> </lnbits-dialog>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('close')"
></q-btn>
</div>
</q-card>
</q-dialog>
<q-dialog v-model="apiAcl.showNewTokenDialog" position="top">
<q-card class="q-pa-md q-pt-md lnbits__dialog-card">
<strong>New API Token</strong>
<div class="row q-col-gutter-md q-mt-md">
<div class="col-12">
<q-input
v-model="apiAcl.newTokenName"
dense
filled
label="Token Name"
>
</q-input>
</div>
<div class="col-12">
<q-input
v-model="apiAcl.newTokenExpiry"
dense
filled
label="Expiration"
hit="Expiration time in minutes (default xxx)"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date
v-model="apiAcl.newTokenExpiry"
mask="YYYY-MM-DD HH:mm"
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append> <lnbits-dialog
<q-icon name="access_time" class="cursor-pointer"> :show="apiAcl.showNewTokenDialog"
<q-popup-proxy title="New API Token"
cover :action="{
transition-show="scale" label: 'Create'
transition-hide="scale" }"
:cancel-label="$t('close')"
@update:show="apiAcl.showNewTokenDialog = $event"
@action="generateApiToken()"
>
<div class="row q-col-gutter-md">
<div class="col-12">
<q-input v-model="apiAcl.newTokenName" dense filled label="Token Name">
</q-input>
</div>
<div class="col-12">
<q-input
v-model="apiAcl.newTokenExpiry"
dense
filled
label="Expiration"
hit="Expiration time in minutes (default xxx)"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="apiAcl.newTokenExpiry" mask="YYYY-MM-DD HH:mm">
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="apiAcl.newTokenExpiry"
mask="YYYY-MM-DD HH:mm"
format24h
> >
<q-time <div class="row items-center justify-end">
v-model="apiAcl.newTokenExpiry" <q-btn v-close-popup label="Close" color="primary" flat />
mask="YYYY-MM-DD HH:mm" </div>
format24h </q-time>
> </q-popup-proxy>
<div class="row items-center justify-end"> </q-icon>
<q-btn v-close-popup label="Close" color="primary" flat /> </template>
</div> </q-input>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
</div> </div>
<div class="row q-mt-lg"> </div>
<q-btn </lnbits-dialog>
@click="generateApiToken()"
label="Create" <lnbits-dialog
color="primary" :show="labelsDialog.show"
></q-btn> :title="$t('label')"
<q-btn :action="{
v-close-popup label: g.user.extra.labels.some(
flat label => label.name === labelsDialog.data.name
color="grey" )
class="q-ml-auto" ? $t('update_label')
v-text="$t('close')" : $t('add_label'),
></q-btn> disable: !labelsDialog.data.name || !labelsDialog.data.color
}"
:cancel-label="$t('cancel')"
@update:show="labelsDialog.show = $event"
@action="
g.user.extra.labels.some(label => label.name === labelsDialog.data.name)
? updateUserLabel()
: addUserLabel()
"
>
<div class="row q-col-gutter-md">
<div class="col-12">
<q-input
v-model="labelsDialog.data.name"
dense
filled
:label="$t('name')"
>
</q-input>
</div> </div>
</q-card> <div class="col-12">
</q-dialog> <q-input
<q-dialog v-model="labelsDialog.show" position="top"> v-model="labelsDialog.data.description"
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> dense
<strong v-text="$t('label')"></strong> filled
<div class="row q-mt-md q-col-gutter-md"> type="textarea"
<div class="col-12"> rows="3"
<q-input :label="$t('description')"
v-model="labelsDialog.data.name" >
dense </q-input>
filled
:label="$t('name')"
>
</q-input>
</div>
<div class="col-12">
<q-input
v-model="labelsDialog.data.description"
dense
filled
type="textarea"
rows="3"
:label="$t('description')"
>
</q-input>
</div>
<div class="col-12">
<q-input
v-model="labelsDialog.data.color"
filled
dense
class="my-input"
>
<template v-slot:append>
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-color
v-model="labelsDialog.data.color"
default-view="palette"
/>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
</div> </div>
<div class="row q-mt-lg"> <div class="col-12">
<q-btn <q-input
v-close-popup v-model="labelsDialog.data.color"
flat filled
color="grey" dense
class="q-ml-auto" class="my-input"
v-text="$t('cancel')" >
></q-btn> <template v-slot:append>
<q-btn <q-icon name="colorize" class="cursor-pointer">
v-if=" <q-popup-proxy
g.user.extra.labels.some( cover
label => label.name === labelsDialog.data.name transition-show="scale"
) transition-hide="scale"
" >
@click="updateUserLabel()" <q-color
:disable="!labelsDialog.data.name || !labelsDialog.data.color" v-model="labelsDialog.data.color"
:label="$t('update_label')" default-view="palette"
color="primary" />
></q-btn> </q-popup-proxy>
<q-btn </q-icon>
v-else </template>
@click="addUserLabel()" </q-input>
:disable="!labelsDialog.data.name || !labelsDialog.data.color"
:label="$t('add_label')"
color="primary"
></q-btn>
</div> </div>
</q-card> </div>
</q-dialog> </lnbits-dialog>
</template> </template>
+19 -29
View File
@@ -170,33 +170,23 @@
</div> </div>
</div> </div>
<q-dialog v-model="auditDetailsDialog.show" position="top"> <lnbits-dialog
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> :show="auditDetailsDialog.show"
<strong v-text="$t('http_request_details')"></strong> :title="$t('http_request_details')"
<q-input :action="{
filled label: $t('copy'),
dense icon: 'content_copy'
v-model.trim="auditDetailsDialog.data" }"
type="textarea" :cancel-label="$t('close')"
rows="25" @update:show="auditDetailsDialog.show = $event"
></q-input> @action="utils.copyText(auditDetailsDialog.data)"
>
<div class="row q-mt-lg"> <q-input
<q-btn filled
@click="utils.copyText(auditDetailsDialog.data)" dense
icon="content_copy" v-model.trim="auditDetailsDialog.data"
color="grey" type="textarea"
flat rows="25"
v-text="$t('copy')" ></q-input>
></q-btn> </lnbits-dialog>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('close')"
></q-btn>
</div>
</q-card>
</q-dialog>
</template> </template>
+114 -129
View File
@@ -366,72 +366,72 @@
</div> </div>
</div> </div>
<q-dialog v-model="showUninstallDialog" position="top"> <lnbits-dialog
<q-card class="q-pa-lg"> :show="showUninstallDialog"
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6> :title="$t('warning')"
<p> :action="{
<span v-text="$t('extension_uninstall_warning')"></span><br /> label: $t('uninstall_confirm')
<span v-text="$t('confirm_continue')"></span> }"
</p> :cancel-label="$t('cancel')"
@update:show="showUninstallDialog = $event"
@action="uninstallExtension()"
>
<p>
<span v-text="$t('extension_uninstall_warning')"></span><br />
<span v-text="$t('confirm_continue')"></span>
</p>
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<q-checkbox <q-checkbox
v-model="uninstallAndDropDb" v-model="uninstallAndDropDb"
value="false" value="false"
label="Cleanup database tables" label="Cleanup database tables"
> >
<q-tooltip class="bg-grey-8" anchor="bottom left" self="top left" <q-tooltip class="bg-grey-8" anchor="bottom left" self="top left"
><span v-text="$t('extension_db_drop_info')"></span> ><span v-text="$t('extension_db_drop_info')"></span>
</q-tooltip> </q-tooltip>
</q-checkbox> </q-checkbox>
</div> </div>
<div class="row q-mt-lg"> </lnbits-dialog>
<q-btn
outline
color="grey"
@click="uninstallExtension()"
v-text="$t('uninstall_confirm')"
></q-btn>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('cancel')"
></q-btn>
</div>
</q-card>
</q-dialog>
<q-dialog v-model="showDropDbDialog" position="top"> <lnbits-dialog
<q-card v-if="selectedExtension" class="q-pa-lg"> v-if="selectedExtension"
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6> :show="showDropDbDialog"
<p><span v-text="$t('extension_db_drop_warning')"></span><br /></p> :title="$t('warning')"
<q-input :action="{
v-model="dropDbExtensionId" label: $t('confirm'),
:label="selectedExtension.id" color: 'red',
></q-input> disable: dropDbExtensionId !== selectedExtension.id
<br /> }"
<p v-text="$t('confirm_continue')"></p> :cancel-label="$t('cancel')"
@update:show="showDropDbDialog = $event"
@action="dropExtensionDb()"
>
<p><span v-text="$t('extension_db_drop_warning')"></span><br /></p>
<q-input
v-model="dropDbExtensionId"
:label="selectedExtension.id"
></q-input>
<br />
<p v-text="$t('confirm_continue')"></p>
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<q-btn <q-btn
:disable="dropDbExtensionId !== selectedExtension.id" :disable="dropDbExtensionId !== selectedExtension.id"
outline outline
color="red" color="red"
@click="dropExtensionDb()" @click="dropExtensionDb()"
v-text="$t('confirm')" v-text="$t('confirm')"
></q-btn> ></q-btn>
<q-btn <q-btn
v-close-popup v-close-popup
flat flat
color="grey" color="grey"
class="q-ml-auto" class="q-ml-auto"
v-text="$t('cancel')" v-text="$t('cancel')"
></q-btn> ></q-btn>
</div> </div>
</q-card> </lnbits-dialog>
</q-dialog>
<q-dialog v-model="showManageExtensionDialog" position="top"> <q-dialog v-model="showManageExtensionDialog" position="top">
<q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card"> <q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card">
@@ -1244,76 +1244,61 @@
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-dialog> </q-dialog>
<q-dialog v-model="paymentDialog.show" position="top"> <lnbits-dialog
<q-card class="q-pa-md lnbits__dialog-card"> :show="paymentDialog.show"
<q-card-section> :cancel-label="$t('close')"
<q-responsive :ratio="1" class="q-mx-xl q-mb-xl"> @update:show="paymentDialog.show = $event"
<lnbits-qrcode >
:value="paymentDialog.invoice" <q-responsive :ratio="1" class="q-mx-xl q-mb-xl">
:options="{width: 800}" <lnbits-qrcode
class="rounded-borders" :value="paymentDialog.invoice"
></lnbits-qrcode> :options="{width: 800}"
</q-responsive> class="rounded-borders"
</q-card-section> ></lnbits-qrcode>
<q-card-actions align="between"> </q-responsive>
<q-btn v-close-popup flat color="grey" :label="$t('close')"></q-btn> </lnbits-dialog>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="showUpdateAllDialog" position="top">
<q-card class="q-pa-md q-pt-md lnbits__dialog-card">
<div class="row">
<div class="col-12">
<h6 class="q-my-md" v-text="$t('update')"></h6>
</div>
</div>
<div v-if="updatableExtensions?.length > 1" class="row">
<div class="col-12">
<q-btn
outline
color="grey"
@click="selectAllUpdatableExtensionss()"
v-text="$t('select_all')"
></q-btn>
</div>
</div>
<q-virtual-scroll :items="updatableExtensions" style="max-height: 400px"> <lnbits-dialog
<template v-slot="{item, index}"> :show="showUpdateAllDialog"
<div class="row"> :title="$t('update')"
<div class="q-col"> :action="{
<q-checkbox label: $t('update')
v-model="item.selectedForUpdate" }"
:disable="item.isUpgraded" :cancel-label="$t('cancel')"
value="false" @update:show="showUpdateAllDialog = $event"
:label="item.name + ` (v${item.latestRelease?.version})`" @action="updateSelectedExtensions()"
> >
<q-spinner-bars <div v-if="updatableExtensions?.length > 1" class="row">
v-if="item.inProgress" <div class="col-12 q-mb-md">
color="primary"
size="1.5em"
class="q-ml-md"
></q-spinner-bars>
</q-checkbox>
</div>
</div>
</template>
</q-virtual-scroll>
<div class="row q-mt-lg">
<q-btn <q-btn
@click="updateSelectedExtensions()"
outline outline
color="grey" color="grey"
v-text="$t('update')" @click="selectAllUpdatableExtensionss()"
></q-btn> v-text="$t('select_all')"
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
v-text="$t('cancel')"
></q-btn> ></q-btn>
</div> </div>
</q-card> </div>
</q-dialog>
<q-virtual-scroll :items="updatableExtensions" style="max-height: 400px">
<template v-slot="{item, index}">
<div class="row">
<div class="q-col">
<q-checkbox
v-model="item.selectedForUpdate"
:disable="item.isUpgraded"
value="false"
:label="item.name + ` (v${item.latestRelease?.version})`"
>
<q-spinner-bars
v-if="item.inProgress"
color="primary"
size="1.5em"
class="q-ml-md"
></q-spinner-bars>
</q-checkbox>
</div>
</div>
</template>
</q-virtual-scroll>
</lnbits-dialog>
</template> </template>
+117 -154
View File
@@ -103,164 +103,127 @@
</q-card-section> </q-card-section>
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="channels"> <q-tab-panel name="channels">
<q-dialog v-model="connectPeerDialog.show" position="top"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card"> :show="connectPeerDialog.show"
<q-form class="q-gutter-md"> :action="{
<q-input label: $t('connect')
dense }"
type="text" :cancel-label="$t('cancel')"
filled @update:show="connectPeerDialog.show = $event"
v-model="connectPeerDialog.data.uri" @action="connectPeer"
label="Node URI" >
hint="pubkey@host:port" <q-form class="q-gutter-md">
></q-input> <q-input
dense
type="text"
filled
v-model="connectPeerDialog.data.uri"
label="Node URI"
hint="pubkey@host:port"
></q-input>
</q-form>
</lnbits-dialog>
<div class="row q-mt-lg"> <lnbits-dialog
<q-btn :show="setFeeDialog.show"
:label="$t('connect')" title="Set Channel Fee"
color="primary" :action="{
@click="connectPeer" label: $t('set')
></q-btn> }"
<q-btn :cancel-label="$t('cancel')"
v-close-popup @update:show="setFeeDialog.show = $event"
flat @action="setChannelFee(setFeeDialog.channel_id)"
color="grey" >
class="q-ml-auto" <p class="text-caption" v-text="setFeeDialog.channel_id"></p>
:label="$t('cancel')" <q-separator></q-separator>
></q-btn> <q-form class="q-gutter-md">
</div> <q-input
</q-form> dense
</q-card> type="number"
</q-dialog> filled
v-model.number="setFeeDialog.data.fee_ppm"
label="Fee Rate PPM"
></q-input>
<q-input
dense
type="number"
filled
v-model.number="setFeeDialog.data.fee_base_msat"
label="Fee Base msat"
></q-input>
</q-form>
</lnbits-dialog>
<q-dialog v-model="setFeeDialog.show"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card"> :show="openChannelDialog.show"
<label class="text-h6">Set Channel Fee</label> :action="{
<p class="text-caption" v-text="setFeeDialog.channel_id"></p> label: $t('open')
<q-separator></q-separator> }"
<q-form class="q-gutter-md"> :cancel-label="$t('cancel')"
<q-input @update:show="openChannelDialog.show = $event"
dense @action="openChannel"
type="number" >
filled <q-form class="q-gutter-md">
v-model.number="setFeeDialog.data.fee_ppm" <q-input
label="Fee Rate PPM" dense
></q-input> type="text"
<q-input filled
dense v-model="openChannelDialog.data.peer_id"
type="number" label="Peer ID"
filled ></q-input>
v-model.number="setFeeDialog.data.fee_base_msat" <q-input
label="Fee Base msat" dense
></q-input> type="number"
filled
v-model.number="openChannelDialog.data.funding_amount"
label="Funding Amount"
></q-input>
<q-expansion-item icon="warning" label="Advanced">
<q-card>
<q-card-section>
<div class="column q-gutter-md">
<q-input
dense
type="number"
filled
v-model.number="openChannelDialog.data.push_amount"
label="Push Amount"
hint="This gifts sats to the other side!"
></q-input>
<div class="row q-mt-lg"> <q-input
<q-btn dense
:label="$t('set')" type="number"
color="primary" filled
@click="setChannelFee(setFeeDialog.channel_id)" v-model.number="openChannelDialog.data.fee_rate"
></q-btn> label="Fee Rate"
<q-btn ></q-input>
v-close-popup </div>
flat </q-card-section>
color="grey" </q-card>
class="q-ml-auto" </q-expansion-item>
:label="$t('cancel')" </q-form>
></q-btn> </lnbits-dialog>
</div>
</q-form>
</q-card>
</q-dialog>
<q-dialog v-model="openChannelDialog.show"> <lnbits-dialog
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card"> :show="closeChannelDialog.show"
<q-form class="q-gutter-md"> title="Close Channel"
<q-input :action="{
dense label: $t('close')
type="text" }"
filled :cancel-label="$t('cancel')"
v-model="openChannelDialog.data.peer_id" @update:show="closeChannelDialog.show = $event"
label="Peer ID" @action="closeChannel"
></q-input> >
<q-input <q-form class="q-gutter-md">
dense <div>
type="number" <q-checkbox
filled v-model="closeChannelDialog.data.force"
v-model.number="openChannelDialog.data.funding_amount" label="Force"
label="Funding Amount" />
></q-input> </div>
<q-expansion-item icon="warning" label="Advanced"> </q-form>
<q-card> </lnbits-dialog>
<q-card-section>
<div class="column q-gutter-md">
<q-input
dense
type="number"
filled
v-model.number="
openChannelDialog.data.push_amount
"
label="Push Amount"
hint="This gifts sats to the other side!"
></q-input>
<q-input
dense
type="number"
filled
v-model.number="openChannelDialog.data.fee_rate"
label="Fee Rate"
></q-input>
</div>
</q-card-section>
</q-card>
</q-expansion-item>
<div class="row q-mt-lg">
<q-btn
:label="$t('open')"
color="primary"
@click="openChannel"
></q-btn>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
:label="$t('cancel')"
></q-btn>
</div>
</q-form>
</q-card>
</q-dialog>
<q-dialog v-model="closeChannelDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
<q-form class="q-gutter-md">
<div>
<q-checkbox
v-model="closeChannelDialog.data.force"
label="Force"
/>
</div>
<div class="row q-mt-lg">
<q-btn
:label="$t('close')"
color="primary"
@click="closeChannel"
></q-btn>
<q-btn
v-close-popup
flat
color="grey"
class="q-ml-auto"
:label="$t('cancel')"
></q-btn>
</div>
</q-form>
</q-card>
</q-dialog>
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<div class="row q-col-gutter-lg"> <div class="row q-col-gutter-lg">
+34 -40
View File
@@ -446,50 +446,44 @@
</div> </div>
</div> </div>
<div v-else-if="activeWallet.show"> <div v-else-if="activeWallet.show">
<q-dialog v-model="createWalletDialog.show" position="top"> <lnbits-dialog
<q-card class="q-pa-md q-pt-md lnbits__dialog-card"> :show="createWalletDialog.show"
<strong>Create Wallet</strong> title="Create Wallet"
<div class="row"> :action="{
<div class="col-12"> label: 'Create',
<div class="row q-mt-lg"> closePopup: true
<div class="col"> }"
<q-input cancel-label="Cancel"
v-model="createWalletDialog.data.name" @update:show="createWalletDialog.show = $event"
:label="$t('name_your_wallet')" @action="createWallet"
filled >
dense <div class="row">
class="q-mb-md" <div class="col-12">
> <div class="row q-mt-lg">
</q-input> <div class="col">
</div> <q-input
</div> v-model="createWalletDialog.data.name"
<div class="row q-mt-lg"> :label="$t('name_your_wallet')"
<div class="col"> filled
<q-select dense
filled class="q-mb-md"
dense
v-model="createWalletDialog.data.currency"
:options="{{ currencies | safe }}"
></q-select>
</div>
</div>
<div class="row q-mt-lg">
<q-btn
v-close-popup
@click="createWallet()"
unelevated
color="primary"
type="submit"
>Create</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
> >
</q-input>
</div>
</div>
<div class="row q-mt-lg">
<div class="col">
<q-select
filled
dense
v-model="createWalletDialog.data.currency"
:options="g.allowedCurrencies"
></q-select>
</div> </div>
</div> </div>
</div> </div>
</q-card> </div>
</q-dialog> </lnbits-dialog>
</div> </div>
<div v-else> <div v-else>
<div class="row q-col-gutter-md q-mb-md"> <div class="row q-col-gutter-md q-mb-md">
+1
View File
@@ -123,6 +123,7 @@
"js/components/admin/lnbits-admin-site-customisation.js", "js/components/admin/lnbits-admin-site-customisation.js",
"js/components/admin/lnbits-admin-assets-config.js", "js/components/admin/lnbits-admin-assets-config.js",
"js/components/admin/lnbits-admin-audit.js", "js/components/admin/lnbits-admin-audit.js",
"js/components/lnbits-dialog.js",
"js/components/lnbits-wallet-charts.js", "js/components/lnbits-wallet-charts.js",
"js/components/lnbits-wallet-api-docs.js", "js/components/lnbits-wallet-api-docs.js",
"js/components/lnbits-wallet-icon.js", "js/components/lnbits-wallet-icon.js",