Compare commits
42
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86a1313258 | ||
|
|
0fa8fca70e | ||
|
|
b33518f075 | ||
|
|
3dce95968e | ||
|
|
7c92788cd8 | ||
|
|
2e31d1fd91 | ||
|
|
6c353f366d | ||
|
|
902f3c7c6f | ||
|
|
7fbffa20d7 | ||
|
|
0185f1e465 | ||
|
|
42b3616b03 | ||
|
|
a446cd6c5b | ||
|
|
3c0c1ca930 | ||
|
|
1a4c706ed4 | ||
|
|
8969c0235d | ||
|
|
34ee5b273a | ||
|
|
c7c1af9465 | ||
|
|
f7ed194e02 | ||
|
|
fd4b6af1de | ||
|
|
342bab5714 | ||
|
|
3d9a882066 | ||
|
|
85b2f30a1a | ||
|
|
07eb0ecdde | ||
|
|
ea0e1e032e | ||
|
|
b23e8ea781 | ||
|
|
fa61016ed1 | ||
|
|
6f44b755e4 | ||
|
|
5997fd74fa | ||
|
|
fb5659de2a | ||
|
|
e13fd39e75 | ||
|
|
acd3b598b7 | ||
|
|
1a6671b4b3 | ||
|
|
7fc723c2dd | ||
|
|
468a786f78 | ||
|
|
f74a7cbe1f | ||
|
|
ce9b63c54e | ||
|
|
3dd1c6992b | ||
|
|
1c49430ece | ||
|
|
b14b3bbaad | ||
|
|
020f6b6b1b | ||
|
|
0314453100 | ||
|
|
37dca56ccc |
@@ -23,6 +23,7 @@ async def create_wallet(
|
|||||||
user=user_id,
|
user=user_id,
|
||||||
adminkey=uuid4().hex,
|
adminkey=uuid4().hex,
|
||||||
inkey=uuid4().hex,
|
inkey=uuid4().hex,
|
||||||
|
currency="USD",
|
||||||
)
|
)
|
||||||
await (conn or db).insert("wallets", wallet)
|
await (conn or db).insert("wallets", wallet)
|
||||||
return wallet
|
return wallet
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<q-select
|
<q-select
|
||||||
v-else-if="['component', 'response_code','request_method'].includes(col.name)"
|
v-else-if="['component', 'response_code','request_method'].includes(col.name)"
|
||||||
v-model="searchData[col.name]"
|
v-model="searchData[col.name]"
|
||||||
@@ -82,6 +83,11 @@
|
|||||||
|
|
||||||
<span v-else v-text="col.label"></span>
|
<span v-else v-text="col.label"></span>
|
||||||
</q-th>
|
</q-th>
|
||||||
|
<q-th>
|
||||||
|
<q-btn flat round icon="settings" tag="a" href="/admin#audit"
|
||||||
|
><q-tooltip v-text="$t('admin_settings')"></q-tooltip
|
||||||
|
></q-btn>
|
||||||
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:body="props">
|
<template v-slot:body="props">
|
||||||
|
|||||||
@@ -286,6 +286,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="theme">
|
<q-tab-panel name="theme">
|
||||||
|
<q-btn
|
||||||
|
v-if="g.user.admin"
|
||||||
|
class="absolute-top-right"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="settings"
|
||||||
|
tag="a"
|
||||||
|
href="/admin#site_customisation"
|
||||||
|
><q-tooltip v-text="$t('admin_settings')"></q-tooltip
|
||||||
|
></q-btn>
|
||||||
<div class="row q-mb-md">
|
<div class="row q-mb-md">
|
||||||
<div class="col-4"><span v-text="$t('language')"></span></div>
|
<div class="col-4"><span v-text="$t('language')"></span></div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
@@ -412,6 +422,22 @@
|
|||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row q-mb-md">
|
||||||
|
<div class="col-4">
|
||||||
|
<span v-text="$t('background_image')"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<q-input
|
||||||
|
v-model="backgroundImage"
|
||||||
|
:label="$t('background_image')"
|
||||||
|
@update:model-value="backgroundImageFunc"
|
||||||
|
>
|
||||||
|
<q-tooltip
|
||||||
|
><span v-text="$t('background_image')"></span
|
||||||
|
></q-tooltip>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row q-mb-md">
|
<div class="row q-mb-md">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<span v-text="$t('gradient_background')"></span>
|
<span v-text="$t('gradient_background')"></span>
|
||||||
|
|||||||
@@ -49,6 +49,15 @@
|
|||||||
v-text="$t('new_version') + ` (${updatableExtensions?.length})`"
|
v-text="$t('new_version') + ` (${updatableExtensions?.length})`"
|
||||||
></span>
|
></span>
|
||||||
</q-badge>
|
</q-badge>
|
||||||
|
<q-btn
|
||||||
|
v-if="g.user.admin"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="settings"
|
||||||
|
tag="a"
|
||||||
|
href="/admin#extensions"
|
||||||
|
><q-tooltip v-text="$t('admin_settings')"></q-tooltip
|
||||||
|
></q-btn>
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,102 +25,124 @@
|
|||||||
} : ''"
|
} : ''"
|
||||||
>
|
>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<q-scroll-area
|
<div class="row">
|
||||||
v-if="!mobileSimple"
|
<div class="col-lg-9 col-12">
|
||||||
style="
|
|
||||||
height: 115px;
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div class="row no-wrap q-gutter-md q-pr-md">
|
|
||||||
<q-card
|
|
||||||
v-for="wallet in g.user.wallets"
|
|
||||||
:key="wallet.id"
|
|
||||||
class="wallet-list-card"
|
|
||||||
bordered
|
|
||||||
tag="a"
|
|
||||||
:href="wallet.url"
|
|
||||||
:style="
|
|
||||||
g.wallet && g.wallet.id === wallet.id
|
|
||||||
? `border: 1px solid ${primaryColor}; width: 250px; text-decoration: none;`
|
|
||||||
: 'width: 250px; text-decoration: none;'
|
|
||||||
"
|
|
||||||
:class="{
|
|
||||||
'active-wallet-card': g.wallet && g.wallet.id === wallet.id
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<q-card-section>
|
|
||||||
<div class="row items-center">
|
|
||||||
<q-avatar
|
|
||||||
size="lg"
|
|
||||||
:color="
|
|
||||||
g.wallet && g.wallet.id === wallet.id
|
|
||||||
? $q.dark.isActive
|
|
||||||
? 'primary'
|
|
||||||
: 'primary'
|
|
||||||
: 'grey-5'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<q-icon
|
|
||||||
name="flash_on"
|
|
||||||
:size="$q.dark.isActive ? '21px' : '20px'"
|
|
||||||
:color="$q.dark.isActive ? 'black' : 'grey-3'"
|
|
||||||
></q-icon>
|
|
||||||
</q-avatar>
|
|
||||||
<div
|
|
||||||
class="text-h6 q-pl-md"
|
|
||||||
:class="{
|
|
||||||
'text-bold': g.wallet && g.wallet.id === wallet.id
|
|
||||||
}"
|
|
||||||
v-text="wallet.name"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
<div class="row items-center q-pt-sm">
|
|
||||||
<h6 class="q-my-none text-no-wrap">
|
|
||||||
<strong v-text="wallet.fsat"></strong>
|
|
||||||
<small> {{LNBITS_DENOMINATION}}</small>
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
</q-scroll-area>
|
|
||||||
<q-card
|
<q-card
|
||||||
:style="$q.screen.lt.md ? {
|
:style="$q.screen.lt.md ? {
|
||||||
background: $q.screen.lt.md ? 'none !important': ''
|
background: $q.screen.lt.md ? 'none !important': ''
|
||||||
, boxShadow: $q.screen.lt.md ? 'none !important': ''
|
, boxShadow: $q.screen.lt.md ? 'none !important': ''
|
||||||
, margin: $q.screen.lt.md && mobileSimple ? 'auto !important': ''
|
, width: $q.screen.lt.md && mobileSimple ? '90% !important': ''
|
||||||
, width: $q.screen.lt.md && mobileSimple ? '90% !important': ''
|
} : ''"
|
||||||
} : ''"
|
|
||||||
>
|
>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<h3 class="q-my-none text-no-wrap">
|
|
||||||
<strong v-text="formattedBalance"></strong>
|
|
||||||
<small> {{LNBITS_DENOMINATION}}</small>
|
|
||||||
<lnbits-update-balance
|
|
||||||
:wallet_id="this.g.wallet.id"
|
|
||||||
@credit-value="handleBalanceUpdate"
|
|
||||||
class="q-ml-md"
|
|
||||||
></lnbits-update-balance>
|
|
||||||
</h3>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col-1" style="max-width: 30px">
|
||||||
<div v-if="g.wallet.currency">
|
<q-btn
|
||||||
|
v-if="update.currency"
|
||||||
|
@click="swapBalancePriority"
|
||||||
|
style="height: 50px"
|
||||||
|
class="q-mt-lg"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
icon="swap_vert"
|
||||||
|
></q-btn>
|
||||||
|
</div>
|
||||||
|
<div class="col-11">
|
||||||
|
<div
|
||||||
|
class="column"
|
||||||
|
:class="{
|
||||||
|
'q-pt-sm': update.currency,
|
||||||
|
'q-pt-lg': !update.currency
|
||||||
|
}"
|
||||||
|
v-if="!isPrioritySwapped"
|
||||||
|
style="height: 90px"
|
||||||
|
>
|
||||||
|
<div class="col-7">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="text-h3 q-my-none text-no-wrap">
|
||||||
|
<strong v-text="formattedBalance"></strong>
|
||||||
|
<small> {{LNBITS_DENOMINATION}}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<lnbits-update-balance
|
||||||
|
v-if="$q.screen.lt.lg"
|
||||||
|
:wallet_id="this.g.wallet.id"
|
||||||
|
:callback="updateBalanceCallback"
|
||||||
|
:small_btn="true"
|
||||||
|
></lnbits-update-balance>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<div v-if="update.currency">
|
||||||
|
<span
|
||||||
|
class="text-h5 text-italic"
|
||||||
|
v-text="formattedFiatAmount"
|
||||||
|
style="opacity: 0.75"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="column"
|
||||||
|
v-if="isPrioritySwapped"
|
||||||
|
:class="{
|
||||||
|
'q-pt-sm': update.currency,
|
||||||
|
'q-pt-lg': !update.currency
|
||||||
|
}"
|
||||||
|
style="height: 100px"
|
||||||
|
>
|
||||||
|
<div class="col-7">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div
|
||||||
|
v-if="update.currency"
|
||||||
|
class="text-h3 q-my-none text-no-wrap"
|
||||||
|
>
|
||||||
|
<strong v-text="formattedFiatAmount"></strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<lnbits-update-balance
|
||||||
|
v-if="$q.screen.lt.lg"
|
||||||
|
:wallet_id="this.g.wallet.id"
|
||||||
|
:callback="updateBalanceCallback"
|
||||||
|
:small_btn="true"
|
||||||
|
></lnbits-update-balance>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<span
|
||||||
|
class="text-h5 text-italic"
|
||||||
|
style="opacity: 0.75"
|
||||||
|
v-text="formattedBalance + ' {{LNBITS_DENOMINATION}}'"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="absolute-right q-pa-md"
|
||||||
|
v-if="$q.screen.gt.md && update.currency"
|
||||||
|
>
|
||||||
|
<div class="text-bold text-italic">BTC Price</div>
|
||||||
<span
|
<span
|
||||||
class="text-h5 text-italic"
|
class="text-bold text-italic"
|
||||||
v-text="formattedFiatBalance"
|
v-text="formattedExchange"
|
||||||
style="opacity: 0.75"
|
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-btn
|
<q-btn
|
||||||
|
v-if="$q.screen.lt.md"
|
||||||
@click="mobileSimple = !mobileSimple"
|
@click="mobileSimple = !mobileSimple"
|
||||||
color="primary"
|
color="primary"
|
||||||
class="float-right lt-md"
|
class="q-ml-xl absolute-right"
|
||||||
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
|
style="height: 20px; margin-top: 75px"
|
||||||
flat
|
flat
|
||||||
:icon="mobileSimple ? 'unfold_more' : 'unfold_less'"
|
:icon="mobileSimple ? 'unfold_more' : 'unfold_less'"
|
||||||
:label="mobileSimple ? $t('more') : $t('less')"
|
:label="mobileSimple ? $t('more') : $t('less')"
|
||||||
@@ -133,35 +155,49 @@
|
|||||||
<q-btn
|
<q-btn
|
||||||
unelevated
|
unelevated
|
||||||
color="primary"
|
color="primary"
|
||||||
class="full-width"
|
class="q-mr-md"
|
||||||
@click="showParseDialog"
|
@click="showParseDialog"
|
||||||
:label="$t('paste_request')"
|
:label="$t('paste_request')"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-btn
|
<q-btn
|
||||||
unelevated
|
unelevated
|
||||||
color="primary"
|
color="primary"
|
||||||
class="full-width"
|
class="q-mr-md"
|
||||||
@click="showReceiveDialog"
|
@click="showReceiveDialog"
|
||||||
:label="$t('create_invoice')"
|
:label="$t('create_invoice')"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
<q-btn unelevated color="secondary" icon="qr_code_scanner">
|
||||||
<div class="col">
|
|
||||||
<q-btn
|
|
||||||
unelevated
|
|
||||||
color="secondary"
|
|
||||||
icon="photo_camera"
|
|
||||||
@click="showCamera"
|
|
||||||
:label="$t('scan')"
|
|
||||||
>
|
|
||||||
<q-tooltip
|
<q-tooltip
|
||||||
><span v-text="$t('camera_tooltip')"></span
|
><span v-text="$t('camera_tooltip')"></span
|
||||||
></q-tooltip>
|
></q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
<lnbits-update-balance
|
||||||
|
v-if="$q.screen.gt.md"
|
||||||
|
:wallet_id="this.g.wallet.id"
|
||||||
|
:callback="updateBalanceCallback"
|
||||||
|
:small_btn="false"
|
||||||
|
></lnbits-update-balance>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-3" v-show="$q.screen.gt.md">
|
||||||
|
<q-card class="q-ml-md q-pa-none" style="height: 172px">
|
||||||
|
<q-card-section style="padding: 0">
|
||||||
|
<canvas
|
||||||
|
ref="transactionChart"
|
||||||
|
style="
|
||||||
|
height: 172px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
transform: translate(-2%, 4%);
|
||||||
|
"
|
||||||
|
></canvas>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<q-card
|
<q-card
|
||||||
:style="
|
:style="
|
||||||
$q.screen.lt.md
|
$q.screen.lt.md
|
||||||
@@ -178,17 +214,14 @@
|
|||||||
:update="updatePayments"
|
:update="updatePayments"
|
||||||
:wallet="this.g.wallet"
|
:wallet="this.g.wallet"
|
||||||
:mobile-simple="mobileSimple"
|
:mobile-simple="mobileSimple"
|
||||||
/>
|
></payment-list>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
{% if HIDE_API %}
|
{% if HIDE_API %}
|
||||||
<div class="col-12 col-md-4 q-gutter-y-md">
|
<div class="col-12 col-md-4 q-gutter-y-md">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div
|
<div v-if="!mobileSimple || $q.screen.gt.sm" class="col-12 col-md-5 q-gutter-y-md">
|
||||||
v-if="!mobileSimple || $q.screen.gt.sm"
|
|
||||||
class="col-12 col-md-5 q-gutter-y-md"
|
|
||||||
>
|
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<h6 class="text-subtitle1 q-mt-none q-mb-sm">
|
<h6 class="text-subtitle1 q-mt-none q-mb-sm">
|
||||||
@@ -277,24 +310,27 @@
|
|||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div style="max-width: 360px">
|
<div style="max-width: 360px">
|
||||||
<q-select
|
<div class="row">
|
||||||
filled
|
<div class="col-auto">
|
||||||
dense
|
<q-toggle
|
||||||
clearable
|
v-model="fiatTracking"
|
||||||
v-model="update.currency"
|
color="primary"
|
||||||
type="text"
|
@update:model-value="handleFiatTracking"
|
||||||
:label="$t('currency')"
|
></q-toggle>
|
||||||
:options="receive.units.filter((u) => u !== 'sat')"
|
</div>
|
||||||
></q-select>
|
<div class="col">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="update.currency"
|
||||||
|
type="text"
|
||||||
|
:label="!fiatTracking ? 'Disabled' : $t('currency')"
|
||||||
|
:options="receive.units.filter((u) => u !== 'sat')"
|
||||||
|
:disable="!fiatTracking"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-btn
|
|
||||||
:disable="!update.name.length"
|
|
||||||
unelevated
|
|
||||||
class="q-mt-sm"
|
|
||||||
color="primary"
|
|
||||||
:label="$t('update_currency')"
|
|
||||||
@click="updateWallet({ currency: update.currency || '' })"
|
|
||||||
></q-btn>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+18
-8
File diff suppressed because one or more lines are too long
@@ -26,6 +26,7 @@ window.localisation.en = {
|
|||||||
close_channel: 'Close Channel',
|
close_channel: 'Close Channel',
|
||||||
close: 'Close',
|
close: 'Close',
|
||||||
restart: 'Restart server',
|
restart: 'Restart server',
|
||||||
|
background_image: 'Background Image',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
save_tooltip: 'Save your changes',
|
save_tooltip: 'Save your changes',
|
||||||
credit_debit: 'Credit / Debit',
|
credit_debit: 'Credit / Debit',
|
||||||
@@ -254,6 +255,7 @@ window.localisation.en = {
|
|||||||
gradient_background: 'Gradient Background',
|
gradient_background: 'Gradient Background',
|
||||||
language: 'Language',
|
language: 'Language',
|
||||||
color_scheme: 'Color Scheme',
|
color_scheme: 'Color Scheme',
|
||||||
|
admin_settings: 'Admin Settings',
|
||||||
extension_cost: 'This release requires a payment of minimum {cost} sats.',
|
extension_cost: 'This release requires a payment of minimum {cost} sats.',
|
||||||
extension_paid_sats: 'You have already paid {paid_sats} sats.',
|
extension_paid_sats: 'You have already paid {paid_sats} sats.',
|
||||||
release_details_error: 'Cannot get the release details.',
|
release_details_error: 'Cannot get the release details.',
|
||||||
|
|||||||
+80
-21
@@ -12,7 +12,12 @@ window.app = Vue.createApp({
|
|||||||
'confettiFireworks',
|
'confettiFireworks',
|
||||||
'confettiStars'
|
'confettiStars'
|
||||||
],
|
],
|
||||||
borderOptions: ['retro-border', 'hard-border', 'no-border'],
|
borderOptions: [
|
||||||
|
'retro-border',
|
||||||
|
'hard-border',
|
||||||
|
'neon-border',
|
||||||
|
'no-border'
|
||||||
|
],
|
||||||
tab: 'user',
|
tab: 'user',
|
||||||
credentialsData: {
|
credentialsData: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -40,28 +45,72 @@ window.app = Vue.createApp({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
applyGradient() {
|
applyGradient() {
|
||||||
darkBgColor = this.$q.localStorage.getItem('lnbits.darkBgColor')
|
this.$q.localStorage.set('lnbits.gradientBg', this.gradientChoice)
|
||||||
primaryColor = this.$q.localStorage.getItem('lnbits.primaryColor')
|
if (this.$q.localStorage.getItem('lnbits.gradientBg')) {
|
||||||
if (this.gradientChoice) {
|
|
||||||
if (!this.$q.dark.isActive) {
|
if (!this.$q.dark.isActive) {
|
||||||
this.toggleDarkMode()
|
this.toggleDarkMode()
|
||||||
}
|
}
|
||||||
|
this.setColors()
|
||||||
|
darkBgColor = this.$q.localStorage.getItem('lnbits.darkBgColor')
|
||||||
|
primaryColor = this.$q.localStorage.getItem('lnbits.primaryColor')
|
||||||
const gradientStyle = `linear-gradient(to bottom right, ${LNbits.utils.hexDarken(String(primaryColor), -70)}, #0a0a0a)`
|
const gradientStyle = `linear-gradient(to bottom right, ${LNbits.utils.hexDarken(String(primaryColor), -70)}, #0a0a0a)`
|
||||||
document.body.style.setProperty(
|
document.body.style.setProperty(
|
||||||
'background-image',
|
'background-image',
|
||||||
gradientStyle,
|
gradientStyle,
|
||||||
'important'
|
'important'
|
||||||
)
|
)
|
||||||
const gradientStyleCards = `background-color: ${LNbits.utils.hexAlpha(String(darkBgColor), 0.4)} !important`
|
const gradientStyleCards = `background-color: ${LNbits.utils.hexAlpha(String(darkBgColor), 0.55)} !important`
|
||||||
const style = document.createElement('style')
|
const style = document.createElement('style')
|
||||||
style.innerHTML =
|
style.innerHTML = `
|
||||||
`body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card:not(.q-dialog .q-card, .lnbits__dialog-card, .q-dialog-plugin--dark), body.body${this.$q.dark.isActive ? '--dark' : ''} .q-header, body.body${this.$q.dark.isActive ? '--dark' : ''} .q-drawer { ${gradientStyleCards} }` +
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card:not(.q-dialog .q-card, .lnbits__dialog-card, .q-dialog-plugin--dark),
|
||||||
`body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"].body--dark{background: ${LNbits.utils.hexDarken(String(primaryColor), -88)} !important; }` +
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-header,
|
||||||
`[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card--dark{background: ${String(darkBgColor)} !important;} }`
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-drawer,
|
||||||
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-tab-panels {
|
||||||
|
${gradientStyleCards}
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"].body--dark {
|
||||||
|
background: ${LNbits.utils.hexDarken(String(primaryColor), -88)} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card--dark {
|
||||||
|
background: ${String(darkBgColor)} !important;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
document.head.appendChild(style)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applyBackgroundImage() {
|
||||||
|
if (this.backgroundImage) {
|
||||||
|
this.$q.localStorage.set('lnbits.backgroundImage', this.backgroundImage)
|
||||||
|
this.gradientChoice = true
|
||||||
|
this.applyGradient()
|
||||||
|
}
|
||||||
|
let bgImage = this.$q.localStorage.getItem('lnbits.backgroundImage')
|
||||||
|
if (bgImage) {
|
||||||
|
this.backgroundImage = bgImage
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.innerHTML = `
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"]::before {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: url(${bgImage});
|
||||||
|
background-size: cover;
|
||||||
|
filter: blur(8px);
|
||||||
|
z-index: -1;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-page-container {
|
||||||
|
backdrop-filter: none; /* Ensure the page content is not affected */
|
||||||
|
}`
|
||||||
document.head.appendChild(style)
|
document.head.appendChild(style)
|
||||||
this.$q.localStorage.set('lnbits.gradientBg', true)
|
|
||||||
} else {
|
|
||||||
this.$q.localStorage.set('lnbits.gradientBg', false)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
applyBorder() {
|
applyBorder() {
|
||||||
@@ -74,6 +123,9 @@ window.app = Vue.createApp({
|
|||||||
if (borderStyle == 'hard-border') {
|
if (borderStyle == 'hard-border') {
|
||||||
borderStyleCSS = `box-shadow: 0 0 0 1px rgba(0,0,0,.12), 0 0 0 1px #ffffff47; border: none;`
|
borderStyleCSS = `box-shadow: 0 0 0 1px rgba(0,0,0,.12), 0 0 0 1px #ffffff47; border: none;`
|
||||||
}
|
}
|
||||||
|
if (borderStyle == 'neon-border') {
|
||||||
|
borderStyleCSS = `border: 2px solid ${this.$q.localStorage.getItem('lnbits.primaryColor')}; box-shadow: none;`
|
||||||
|
}
|
||||||
if (borderStyle == 'no-border') {
|
if (borderStyle == 'no-border') {
|
||||||
borderStyleCSS = `box-shadow: none; border: none;`
|
borderStyleCSS = `box-shadow: none; border: none;`
|
||||||
}
|
}
|
||||||
@@ -87,6 +139,8 @@ window.app = Vue.createApp({
|
|||||||
toggleGradient() {
|
toggleGradient() {
|
||||||
this.gradientChoice = !this.gradientChoice
|
this.gradientChoice = !this.gradientChoice
|
||||||
this.applyGradient()
|
this.applyGradient()
|
||||||
|
this.$q.localStorage.set('lnbits.backgroundImage', '')
|
||||||
|
this.applyBorder()
|
||||||
if (!this.gradientChoice) {
|
if (!this.gradientChoice) {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
@@ -95,13 +149,17 @@ window.app = Vue.createApp({
|
|||||||
reactionChoiceFunc() {
|
reactionChoiceFunc() {
|
||||||
this.$q.localStorage.set('lnbits.reactions', this.reactionChoice)
|
this.$q.localStorage.set('lnbits.reactions', this.reactionChoice)
|
||||||
},
|
},
|
||||||
changeColor(newValue) {
|
backgroundImageFunc() {
|
||||||
|
this.$q.localStorage.set('lnbits.backgroundImage', this.backgroundImage)
|
||||||
|
this.applyBackgroundImage()
|
||||||
|
},
|
||||||
|
changeColor: function (newValue) {
|
||||||
document.body.setAttribute('data-theme', newValue)
|
document.body.setAttribute('data-theme', newValue)
|
||||||
this.$q.localStorage.set('lnbits.theme', newValue)
|
this.$q.localStorage.set('lnbits.theme', newValue)
|
||||||
this.setColors()
|
this.setColors()
|
||||||
if (this.$q.localStorage.getItem('lnbits.gradientBg')) {
|
this.applyGradient()
|
||||||
this.applyGradient()
|
this.applyBackgroundImage()
|
||||||
}
|
this.applyBorder()
|
||||||
},
|
},
|
||||||
async updateAccount() {
|
async updateAccount() {
|
||||||
try {
|
try {
|
||||||
@@ -208,11 +266,12 @@ window.app = Vue.createApp({
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
LNbits.utils.notifyApiError(e)
|
LNbits.utils.notifyApiError(e)
|
||||||
}
|
}
|
||||||
if (this.$q.localStorage.getItem('lnbits.gradientBg')) {
|
const hash = window.location.hash.replace('#', '')
|
||||||
this.applyGradient()
|
if (hash) {
|
||||||
}
|
this.tab = hash
|
||||||
if (this.$q.localStorage.getItem('lnbits.border')) {
|
|
||||||
this.applyBorder()
|
|
||||||
}
|
}
|
||||||
|
this.applyGradient()
|
||||||
|
this.applyBackgroundImage()
|
||||||
|
this.applyBorder()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -122,6 +122,10 @@ window.app = Vue.createApp({
|
|||||||
this.getSettings()
|
this.getSettings()
|
||||||
this.getAudit()
|
this.getAudit()
|
||||||
this.balance = +'{{ balance|safe }}'
|
this.balance = +'{{ balance|safe }}'
|
||||||
|
const hash = window.location.hash.replace('#', '')
|
||||||
|
if (hash) {
|
||||||
|
this.tab = hash
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
lnbitsVersion() {
|
lnbitsVersion() {
|
||||||
|
|||||||
@@ -453,8 +453,10 @@ window.windowMixin = {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
toggleSubs: true,
|
toggleSubs: true,
|
||||||
|
walletFlip: true,
|
||||||
reactionChoice: 'confettiBothSides',
|
reactionChoice: 'confettiBothSides',
|
||||||
borderChoice: '',
|
borderChoice: '',
|
||||||
|
backgroundImage: '',
|
||||||
gradientChoice:
|
gradientChoice:
|
||||||
this.$q.localStorage.getItem('lnbits.gradientBg') || false,
|
this.$q.localStorage.getItem('lnbits.gradientBg') || false,
|
||||||
isUserAuthorized: false,
|
isUserAuthorized: false,
|
||||||
@@ -472,6 +474,17 @@ window.windowMixin = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
flipWallets(smallScreen) {
|
||||||
|
this.walletFlip = !this.walletFlip
|
||||||
|
if (this.walletFlip && smallScreen) {
|
||||||
|
this.g.visibleDrawer = false
|
||||||
|
}
|
||||||
|
this.$q.localStorage.set('lnbits.walletFlip', this.walletFlip)
|
||||||
|
},
|
||||||
|
simpleMobile() {
|
||||||
|
this.mobileSimple = !this.mobileSimple
|
||||||
|
this.$q.localStorage.set('lnbits.mobileSimple', this.mobileSimple)
|
||||||
|
},
|
||||||
changeColor(newValue) {
|
changeColor(newValue) {
|
||||||
document.body.setAttribute('data-theme', newValue)
|
document.body.setAttribute('data-theme', newValue)
|
||||||
this.$q.localStorage.set('lnbits.theme', newValue)
|
this.$q.localStorage.set('lnbits.theme', newValue)
|
||||||
@@ -487,12 +500,54 @@ window.windowMixin = {
|
|||||||
gradientStyle,
|
gradientStyle,
|
||||||
'important'
|
'important'
|
||||||
)
|
)
|
||||||
const gradientStyleCards = `background-color: ${LNbits.utils.hexAlpha(String(darkBgColor), 0.4)} !important`
|
const gradientStyleCards = `background-color: ${LNbits.utils.hexAlpha(String(darkBgColor), 0.55)} !important`
|
||||||
const style = document.createElement('style')
|
const style = document.createElement('style')
|
||||||
style.innerHTML =
|
style.innerHTML = `
|
||||||
`body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card:not(.q-dialog .q-card, .lnbits__dialog-card, .q-dialog-plugin--dark), body.body${this.$q.dark.isActive ? '--dark' : ''} .q-header, body.body${this.$q.dark.isActive ? '--dark' : ''} .q-drawer { ${gradientStyleCards} }` +
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card:not(.q-dialog .q-card, .lnbits__dialog-card, .q-dialog-plugin--dark),
|
||||||
`body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"].body--dark{background: ${LNbits.utils.hexDarken(String(primaryColor), -88)} !important; }` +
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-header,
|
||||||
`[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card--dark{background: ${String(darkBgColor)} !important;} }`
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-drawer,
|
||||||
|
body.body${this.$q.dark.isActive ? '--dark' : ''} .q-tab-panels {
|
||||||
|
${gradientStyleCards}
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"].body--dark {
|
||||||
|
background: ${LNbits.utils.hexDarken(String(primaryColor), -88)} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-card--dark {
|
||||||
|
background: ${String(darkBgColor)} !important;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
document.head.appendChild(style)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applyBackgroundImage() {
|
||||||
|
if (this.backgroundImage) {
|
||||||
|
this.$q.localStorage.set('lnbits.backgroundImage', this.backgroundImage)
|
||||||
|
}
|
||||||
|
let bgImage = this.$q.localStorage.getItem('lnbits.backgroundImage')
|
||||||
|
if (bgImage) {
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.innerHTML = `
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"]::before {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: url(${bgImage});
|
||||||
|
background-size: cover;
|
||||||
|
filter: blur(8px);
|
||||||
|
z-index: -1;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="${this.$q.localStorage.getItem('lnbits.theme')}"] .q-page-container {
|
||||||
|
backdrop-filter: none; /* Ensure the page content is not affected */
|
||||||
|
}`
|
||||||
document.head.appendChild(style)
|
document.head.appendChild(style)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -510,6 +565,9 @@ window.windowMixin = {
|
|||||||
if (borderStyle == 'hard-border') {
|
if (borderStyle == 'hard-border') {
|
||||||
borderStyleCSS = `box-shadow: 0 0 0 1px rgba(0,0,0,.12), 0 0 0 1px #ffffff47; border: none;`
|
borderStyleCSS = `box-shadow: 0 0 0 1px rgba(0,0,0,.12), 0 0 0 1px #ffffff47; border: none;`
|
||||||
}
|
}
|
||||||
|
if (borderStyle == 'neon-border') {
|
||||||
|
borderStyleCSS = `border: 2px solid ${this.$q.localStorage.getItem('lnbits.primaryColor')}; box-shadow: none;`
|
||||||
|
}
|
||||||
if (borderStyle == 'no-border') {
|
if (borderStyle == 'no-border') {
|
||||||
borderStyleCSS = `box-shadow: none; border: none;`
|
borderStyleCSS = `box-shadow: none; border: none;`
|
||||||
}
|
}
|
||||||
@@ -686,6 +744,7 @@ window.windowMixin = {
|
|||||||
|
|
||||||
this.applyGradient()
|
this.applyGradient()
|
||||||
this.applyBorder()
|
this.applyBorder()
|
||||||
|
this.applyBackgroundImage()
|
||||||
|
|
||||||
if (window.user) {
|
if (window.user) {
|
||||||
this.g.user = Object.freeze(window.LNbits.map.user(window.user))
|
this.g.user = Object.freeze(window.LNbits.map.user(window.user))
|
||||||
@@ -700,6 +759,8 @@ window.windowMixin = {
|
|||||||
}
|
}
|
||||||
await this.checkUsrInUrl()
|
await this.checkUsrInUrl()
|
||||||
this.themeParams()
|
this.themeParams()
|
||||||
|
this.walletFlip = this.$q.localStorage.getItem('lnbits.walletFlip')
|
||||||
|
this.mobileSimple = this.$q.localStorage.getItem('lnbits.mobileSimple')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ window.app.component('lnbits-dynamic-chips', {
|
|||||||
window.app.component('lnbits-update-balance', {
|
window.app.component('lnbits-update-balance', {
|
||||||
template: '#lnbits-update-balance',
|
template: '#lnbits-update-balance',
|
||||||
mixins: [window.windowMixin],
|
mixins: [window.windowMixin],
|
||||||
props: ['wallet_id', 'credit-value'],
|
props: ['wallet_id', 'credit-value', 'small_btn'],
|
||||||
computed: {
|
computed: {
|
||||||
denomination() {
|
denomination() {
|
||||||
return LNBITS_DENOMINATION
|
return LNBITS_DENOMINATION
|
||||||
|
|||||||
+189
-22
@@ -7,6 +7,7 @@ window.app = Vue.createApp({
|
|||||||
origin: window.location.origin,
|
origin: window.location.origin,
|
||||||
wallet: LNbits.map.wallet(window.wallet),
|
wallet: LNbits.map.wallet(window.wallet),
|
||||||
user: LNbits.map.user(window.user),
|
user: LNbits.map.user(window.user),
|
||||||
|
mobileSimple: false,
|
||||||
exportUrl: `${window.location.origin}/wallet?usr=${window.user.id}&wal=${window.wallet.id}`,
|
exportUrl: `${window.location.origin}/wallet?usr=${window.user.id}&wal=${window.wallet.id}`,
|
||||||
baseUrl: `${window.location.protocol}//${window.location.host}/`,
|
baseUrl: `${window.location.protocol}//${window.location.host}/`,
|
||||||
receive: {
|
receive: {
|
||||||
@@ -50,7 +51,6 @@ window.app = Vue.createApp({
|
|||||||
},
|
},
|
||||||
balance: parseInt(wallet.balance_msat / 1000),
|
balance: parseInt(wallet.balance_msat / 1000),
|
||||||
fiatBalance: 0,
|
fiatBalance: 0,
|
||||||
mobileSimple: false,
|
|
||||||
update: {
|
update: {
|
||||||
name: null,
|
name: null,
|
||||||
currency: null
|
currency: null
|
||||||
@@ -59,7 +59,16 @@ window.app = Vue.createApp({
|
|||||||
adminkeyHidden: true,
|
adminkeyHidden: true,
|
||||||
hasNfc: false,
|
hasNfc: false,
|
||||||
nfcReaderAbortController: null,
|
nfcReaderAbortController: null,
|
||||||
primaryColor: this.$q.localStorage.getItem('lnbits.primaryColor')
|
isPrioritySwapped: false,
|
||||||
|
fiatTracking: false,
|
||||||
|
formattedFiatAmount: 0,
|
||||||
|
exchangeRate: 0,
|
||||||
|
formattedExchange: null,
|
||||||
|
ignoreWatcher: true,
|
||||||
|
primaryColor: this.$q.localStorage.getItem('lnbits.primaryColor'),
|
||||||
|
transactions: [],
|
||||||
|
transactionChart: null,
|
||||||
|
paymentsRef: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -70,14 +79,6 @@ window.app = Vue.createApp({
|
|||||||
return LNbits.utils.formatSat(this.balance || this.g.wallet.sat)
|
return LNbits.utils.formatSat(this.balance || this.g.wallet.sat)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formattedFiatBalance() {
|
|
||||||
if (this.fiatBalance) {
|
|
||||||
return LNbits.utils.formatCurrency(
|
|
||||||
this.fiatBalance.toFixed(2),
|
|
||||||
this.g.wallet.currency
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
canPay() {
|
canPay() {
|
||||||
if (!this.parse.invoice) return false
|
if (!this.parse.invoice) return false
|
||||||
return this.parse.invoice.sat <= this.balance
|
return this.parse.invoice.sat <= this.balance
|
||||||
@@ -97,6 +98,95 @@ window.app = Vue.createApp({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatFiatAmount(amount, currency) {
|
||||||
|
this.update.currency = currency
|
||||||
|
this.formattedFiatAmount = LNbits.utils.formatCurrency(
|
||||||
|
amount.toFixed(2),
|
||||||
|
currency
|
||||||
|
)
|
||||||
|
this.formattedExchange = LNbits.utils.formatCurrency(
|
||||||
|
this.exchangeRate,
|
||||||
|
currency
|
||||||
|
)
|
||||||
|
},
|
||||||
|
computeCumulativeBalance(transactions) {
|
||||||
|
let balance = 0
|
||||||
|
return transactions.map(transaction => {
|
||||||
|
balance += transaction.amount // Use the amount field for the balance
|
||||||
|
return balance
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
initCharts() {
|
||||||
|
this.transactionChart = new Chart(
|
||||||
|
this.$refs.transactionChart.getContext('2d'),
|
||||||
|
{
|
||||||
|
type: 'line',
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
layout: {
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
enabled: true, // Enable tooltips to show data on hover
|
||||||
|
callbacks: {
|
||||||
|
// Custom tooltip callback to show amount and time
|
||||||
|
label: tooltipItem => {
|
||||||
|
const index = tooltipItem.dataIndex
|
||||||
|
const transaction = this.transactions[index] // Match tooltip point with transaction
|
||||||
|
const amount = transaction.amount
|
||||||
|
return [
|
||||||
|
`Balance: ${tooltipItem.raw / 1000}sats`, // Display cumulative balance
|
||||||
|
`Amount: ${amount / 1000}sats`
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 4, // Points will now be visible
|
||||||
|
hoverRadius: 6 // Increase point size on hover
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
labels: this.transactions.map(
|
||||||
|
tx => new Date(tx.time).toLocaleString() // Use time for labels
|
||||||
|
),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Cumulative Balance',
|
||||||
|
data: this.computeCumulativeBalance(this.transactions),
|
||||||
|
backgroundColor: LNbits.utils.hexAlpha(this.primaryColor, 0.3),
|
||||||
|
borderColor: this.primaryColor,
|
||||||
|
borderWidth: 2,
|
||||||
|
fill: true,
|
||||||
|
tension: 0.2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
msatoshiFormat(value) {
|
msatoshiFormat(value) {
|
||||||
return LNbits.utils.formatSat(value / 1000)
|
return LNbits.utils.formatSat(value / 1000)
|
||||||
},
|
},
|
||||||
@@ -515,7 +605,6 @@ window.app = Vue.createApp({
|
|||||||
type: 'positive',
|
type: 'positive',
|
||||||
timeout: 3500
|
timeout: 3500
|
||||||
})
|
})
|
||||||
window.location.reload()
|
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
LNbits.utils.notifyApiError(err)
|
LNbits.utils.notifyApiError(err)
|
||||||
@@ -539,15 +628,23 @@ window.app = Vue.createApp({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateFiatBalance() {
|
updateFiatBalance(currency) {
|
||||||
if (!this.g.wallet.currency) return 0
|
// set rate from local storage to avoid clunky api calls
|
||||||
|
this.exchangeRate = this.$q.localStorage.getItem('lnbits.exchangeRate')
|
||||||
|
this.fiatBalance =
|
||||||
|
(this.exchangeRate / 100000000) * (this.balance || this.g.wallet.sat)
|
||||||
|
this.formatFiatAmount(this.fiatBalance, currency)
|
||||||
|
// make api call
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request('POST', `/api/v1/conversion`, null, {
|
.request('GET', `/api/v1/rate/` + currency, null)
|
||||||
amount: this.balance || this.g.wallet.sat,
|
|
||||||
to: this.g.wallet.currency
|
|
||||||
})
|
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.fiatBalance = response.data[this.g.wallet.currency]
|
this.fiatBalance =
|
||||||
|
(response.data.price / 100000000) *
|
||||||
|
(this.balance || this.g.wallet.sat)
|
||||||
|
this.exchangeRate = response.data.price.toFixed(2)
|
||||||
|
this.fiatTracking = true
|
||||||
|
this.formatFiatAmount(this.fiatBalance, currency)
|
||||||
|
this.$q.localStorage.set('lnbits.exchangeRate', this.exchangeRate)
|
||||||
})
|
})
|
||||||
.catch(e => console.error(e))
|
.catch(e => console.error(e))
|
||||||
},
|
},
|
||||||
@@ -652,6 +749,48 @@ window.app = Vue.createApp({
|
|||||||
dismissPaymentMsg()
|
dismissPaymentMsg()
|
||||||
LNbits.utils.notifyApiError(err)
|
LNbits.utils.notifyApiError(err)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
handleWallet(wallet) {
|
||||||
|
console.log('Wallet from child:', wallet)
|
||||||
|
},
|
||||||
|
fetchPayments() {
|
||||||
|
return LNbits.api
|
||||||
|
.getPayments(
|
||||||
|
this.g.wallet,
|
||||||
|
'sortby=time&direction=asc&status[ne]=failed'
|
||||||
|
)
|
||||||
|
.then(response => {
|
||||||
|
console.log(response.data.data)
|
||||||
|
for (let payment of response.data.data) {
|
||||||
|
record = {
|
||||||
|
payment_hash: payment.payment_hash,
|
||||||
|
amount: payment.amount,
|
||||||
|
description: payment.description,
|
||||||
|
time: payment.time
|
||||||
|
}
|
||||||
|
this.transactions.push(record)
|
||||||
|
}
|
||||||
|
console.log(this.transactions)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.paymentsTable.loading = false
|
||||||
|
LNbits.utils.notifyApiError(err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
swapBalancePriority() {
|
||||||
|
this.isPrioritySwapped = !this.isPrioritySwapped
|
||||||
|
this.$q.localStorage.setItem(
|
||||||
|
'lnbits.isPrioritySwapped',
|
||||||
|
this.isPrioritySwapped
|
||||||
|
)
|
||||||
|
},
|
||||||
|
handleFiatTracking() {
|
||||||
|
if (this.fiatTracking === false) {
|
||||||
|
this.update.currency = ''
|
||||||
|
this.$q.localStorage.setItem('lnbits.isPrioritySwapped', false)
|
||||||
|
this.isPrioritySwapped = false
|
||||||
|
this.$q.localStorage.remove(`lnbits.exchangeRate`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -665,20 +804,39 @@ window.app = Vue.createApp({
|
|||||||
if (this.$q.screen.lt.md) {
|
if (this.$q.screen.lt.md) {
|
||||||
this.mobileSimple = true
|
this.mobileSimple = true
|
||||||
}
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.ignoreWatcher = false
|
||||||
|
}, 3000)
|
||||||
|
if (this.g.wallet.currency) {
|
||||||
|
this.fiatTracking = true
|
||||||
|
this.updateFiatBalance(this.g.wallet.currency)
|
||||||
|
}
|
||||||
this.update.name = this.g.wallet.name
|
this.update.name = this.g.wallet.name
|
||||||
this.update.currency = this.g.wallet.currency
|
|
||||||
this.receive.units = ['sat', ...window.currencies]
|
this.receive.units = ['sat', ...window.currencies]
|
||||||
this.updateFiatBalance()
|
this.fetchPayments().then(() => {
|
||||||
|
this.initCharts()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
'$q.screen.gt.sm'(value) {
|
||||||
|
if (value == true) {
|
||||||
|
this.mobileSimple = false
|
||||||
|
}
|
||||||
|
},
|
||||||
updatePayments() {
|
updatePayments() {
|
||||||
this.updateFiatBalance()
|
this.fetchBalance()
|
||||||
|
},
|
||||||
|
'update.currency'(newValue) {
|
||||||
|
if (this.ignoreWatcher || this.update.currency == '') return
|
||||||
|
this.updateWallet({currency: newValue})
|
||||||
|
this.updateFiatBalance(newValue)
|
||||||
},
|
},
|
||||||
'$q.screen.gt.sm'(value) {
|
'$q.screen.gt.sm'(value) {
|
||||||
if (value == true) {
|
if (value == true) {
|
||||||
this.mobileSimple = false
|
this.mobileSimple = false
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// show disclaimer
|
// show disclaimer
|
||||||
@@ -686,6 +844,15 @@ window.app = Vue.createApp({
|
|||||||
this.disclaimerDialog.show = true
|
this.disclaimerDialog.show = true
|
||||||
this.$q.localStorage.set('lnbits.disclaimerShown', true)
|
this.$q.localStorage.set('lnbits.disclaimerShown', true)
|
||||||
}
|
}
|
||||||
|
// check blanace priority
|
||||||
|
if (this.$q.localStorage.getItem('lnbits.isPrioritySwapped')) {
|
||||||
|
this.isPrioritySwapped = this.$q.localStorage.getItem(
|
||||||
|
'lnbits.isPrioritySwapped'
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.isPrioritySwapped = false
|
||||||
|
this.$q.localStorage.setItem('lnbits.isPrioritySwapped', false)
|
||||||
|
}
|
||||||
// listen to incoming payments
|
// listen to incoming payments
|
||||||
LNbits.events.onInvoicePaid(this.g.wallet, data => {
|
LNbits.events.onInvoicePaid(this.g.wallet, data => {
|
||||||
console.log('Payment received:', data.payment.payment_hash)
|
console.log('Payment received:', data.payment.payment_hash)
|
||||||
|
|||||||
@@ -131,6 +131,21 @@
|
|||||||
<q-item-label> </q-item-label>
|
<q-item-label> </q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
<q-item tag="a" href="/account#theme" clickable v-close-popup
|
||||||
|
><q-item-section>
|
||||||
|
<q-icon
|
||||||
|
:name="$q.dark.isActive ? 'dark_mode' : 'light_mode'"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<span v-text="$t('theme')"></span>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label> </q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
<q-separator></q-separator>
|
<q-separator></q-separator>
|
||||||
<q-item clickable v-close-popup @click="logout"
|
<q-item clickable v-close-popup @click="logout"
|
||||||
><q-item-section>
|
><q-item-section>
|
||||||
@@ -158,7 +173,22 @@
|
|||||||
show-if-above
|
show-if-above
|
||||||
:elevated="$q.screen.lt.md"
|
:elevated="$q.screen.lt.md"
|
||||||
>
|
>
|
||||||
<lnbits-wallet-list :balance="balance"></lnbits-wallet-list>
|
<q-item-label
|
||||||
|
:style="$q.dark.isActive ? 'color:rgba(255, 255, 255, 0.64)' : ''"
|
||||||
|
class="q-item__label q-item__label--header"
|
||||||
|
header
|
||||||
|
v-text="$t('wallets')"
|
||||||
|
></q-item-label>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
:icon=" walletFlip ? 'keyboard_arrow_right' : 'keyboard_arrow_down'"
|
||||||
|
class="absolute-top-right"
|
||||||
|
@click="flipWallets($q.screen.lt.md)"
|
||||||
|
></q-btn>
|
||||||
|
<lnbits-wallet-list
|
||||||
|
v-if="!walletFlip"
|
||||||
|
:balance="balance"
|
||||||
|
></lnbits-wallet-list>
|
||||||
|
|
||||||
<lnbits-manage
|
<lnbits-manage
|
||||||
:show-admin="'{{LNBITS_ADMIN_UI}}' == 'True'"
|
:show-admin="'{{LNBITS_ADMIN_UI}}' == 'True'"
|
||||||
@@ -172,6 +202,68 @@
|
|||||||
{% endblock %} {% block page_container %}
|
{% endblock %} {% block page_container %}
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
<q-page class="q-px-md q-py-lg" :class="{'q-px-lg': $q.screen.gt.xs}">
|
<q-page class="q-px-md q-py-lg" :class="{'q-px-lg': $q.screen.gt.xs}">
|
||||||
|
<q-scroll-area
|
||||||
|
v-if="walletFlip"
|
||||||
|
style="
|
||||||
|
height: 130px;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="row no-wrap q-gutter-md q-pr-md">
|
||||||
|
<q-card
|
||||||
|
v-for="wallet in g.user.wallets"
|
||||||
|
:key="wallet.id"
|
||||||
|
class="wallet-list-card"
|
||||||
|
tag="a"
|
||||||
|
:href="wallet.url"
|
||||||
|
:style="
|
||||||
|
g.wallet && g.wallet.id === wallet.id
|
||||||
|
? `border: 1px solid ${primaryColor}; width: 250px; text-decoration: none;`
|
||||||
|
: 'width: 250px; text-decoration: none; border: 0px'
|
||||||
|
"
|
||||||
|
:class="{
|
||||||
|
'active-wallet-card': g.wallet && g.wallet.id === wallet.id
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row items-center">
|
||||||
|
<q-avatar
|
||||||
|
size="lg"
|
||||||
|
:color="
|
||||||
|
g.wallet && g.wallet.id === wallet.id
|
||||||
|
? $q.dark.isActive
|
||||||
|
? 'primary'
|
||||||
|
: 'primary'
|
||||||
|
: 'grey-5'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-icon
|
||||||
|
name="flash_on"
|
||||||
|
:size="$q.dark.isActive ? '21px' : '20px'"
|
||||||
|
:color="$q.dark.isActive ? 'black' : 'grey-3'"
|
||||||
|
></q-icon>
|
||||||
|
</q-avatar>
|
||||||
|
<div
|
||||||
|
class="text-h6 q-pl-md"
|
||||||
|
:class="{
|
||||||
|
'text-bold': g.wallet && g.wallet.id === wallet.id
|
||||||
|
}"
|
||||||
|
v-text="wallet.name"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center q-pt-sm">
|
||||||
|
<h6 class="q-my-none text-no-wrap">
|
||||||
|
<strong v-text="wallet.fsat"></strong>
|
||||||
|
<small> {{LNBITS_DENOMINATION}}</small>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</q-scroll-area>
|
||||||
|
|
||||||
{% block page %}{% endblock %}
|
{% block page %}{% endblock %}
|
||||||
</q-page>
|
</q-page>
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
dense
|
dense
|
||||||
class="lnbits-drawer__q-list"
|
class="lnbits-drawer__q-list"
|
||||||
>
|
>
|
||||||
<q-item-label header v-text="$t('wallets')"></q-item-label>
|
|
||||||
<q-item
|
<q-item
|
||||||
v-for="wallet in wallets"
|
v-for="wallet in wallets"
|
||||||
:key="wallet.id"
|
:key="wallet.id"
|
||||||
@@ -53,7 +52,6 @@
|
|||||||
side
|
side
|
||||||
v-show="activeWallet && activeWallet.id === wallet.id"
|
v-show="activeWallet && activeWallet.id === wallet.id"
|
||||||
>
|
>
|
||||||
<q-icon name="chevron_right" color="grey-5" size="md"></q-icon>
|
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item clickable @click="showForm = !showForm">
|
<q-item clickable @click="showForm = !showForm">
|
||||||
@@ -506,7 +504,38 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="lnbits-update-balance">
|
<template id="lnbits-update-balance">
|
||||||
<q-btn v-if="admin" :label="$t('credit_debit')" color="secondary" size="sm">
|
<q-btn
|
||||||
|
v-if="admin && small_btn"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
icon="add"
|
||||||
|
>
|
||||||
|
<q-popup-edit class="bg-accent text-white" v-slot="scope" v-model="credit">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
:label="$t('credit_label', {denomination: denomination})"
|
||||||
|
v-model="scope.value"
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
@keyup.enter="scope.set"
|
||||||
|
>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="edit" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-popup-edit>
|
||||||
|
<q-tooltip v-text="$t('credit_hint')"></q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
|
||||||
|
<q-btn
|
||||||
|
v-if="admin && !small_btn"
|
||||||
|
color="primary"
|
||||||
|
:label="$t('credit_debit')"
|
||||||
|
class="float-right q-mt-sm"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
<q-popup-edit class="bg-accent text-white" v-slot="scope" v-model="credit">
|
<q-popup-edit class="bg-accent text-white" v-slot="scope" v-model="credit">
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
|
|||||||
Reference in New Issue
Block a user