Chart polish (#2973)

This commit is contained in:
Vlad Stan 2025-02-17 14:30:16 +02:00 committed by GitHub
parent 60de308c8f
commit c08623277e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 170 additions and 130 deletions

View file

@ -440,6 +440,8 @@ async def get_payments_daily_stats(
balance_total: float = 0
_none = PaymentDailyStats(date=datetime.now(timezone.utc))
if len(data_in) == 0 and len(data_out) == 0:
return []
if len(data_in) == 0:
data_in = [_none]
if len(data_out) == 0:

View file

@ -4,34 +4,43 @@
<!---->
{% block scripts %} {{ window_vars(user) }}{% endblock %} {% block page %}
<div class="row q-col-gutter-md q-mb-md">
<div class="col-12">
<q-card>
<div>
<div class="q-gutter-y-md">
<q-tabs v-model="tab" align="left">
<q-tab
name="user"
:label="$t('account_settings')"
@update="val => tab = val.name"
></q-tab>
<q-tab
name="theme"
:label="$t('look_and_feel')"
@update="val => tab = val.name"
></q-tab>
<q-tab
name="api_acls"
:label="$t('access_control_list')"
@update="val => tab = val.name"
></q-tab>
</q-tabs>
</div>
</div>
</q-card>
</div>
</div>
<div class="row q-col-gutter-md">
<div v-if="user" class="col-md-12 col-lg-6 q-gutter-y-md">
<q-card>
<q-card-section>
<div class="row">
<div class="col">
<q-tabs v-model="tab" align="justify">
<q-tab
name="user"
:label="$t('account_settings')"
@update="val => tab = val.name"
></q-tab>
<q-tab
name="theme"
:label="$t('look_and_feel')"
@update="val => tab = val.name"
></q-tab>
<q-tab
name="api_acls"
:label="$t('access_control_list')"
@update="val => tab = val.name"
></q-tab>
</q-tabs>
<q-tab-panels v-model="tab">
<q-tab-panel name="user">
<div v-if="credentialsData.show">
<q-separator></q-separator>
<q-card-section>
<div class="row">
<div class="col">
@ -132,11 +141,10 @@
</q-card-section>
</div>
<div v-else>
<q-card-section>
<q-card-section v-if="user.extra.picture">
<div class="row">
<div class="col">
<q-img
v-if="user.extra.picture"
style="max-width: 100px"
:src="user.extra.picture"
class="float-right"
@ -144,7 +152,6 @@
</div>
</div>
</q-card-section>
<q-separator></q-separator>
<q-card-section>
<q-input

View file

@ -481,27 +481,37 @@
>{% endfor %}
</q-card>
{% endif %}
<q-card v-if="chartConfig.showBalance">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletBalanceChart"></canvas>
</div>
</q-card-section>
</q-card>
<q-card v-if="chartConfig.showBalanceInOut">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletBalanceInOut"></canvas>
</div>
</q-card-section>
</q-card>
<q-card v-if="chartConfig.showPaymentCountInOut">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletPaymentsInOut"></canvas>
</div>
</q-card-section>
</q-card>
<div
v-show="chartDataPointCount"
class="col-12 col-md-5 q-gutter-y-md"
>
<q-card v-if="chartConfig.showBalance">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletBalanceChart"></canvas>
</div>
</q-card-section>
</q-card>
<q-card v-if="chartConfig.showBalanceInOut">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletBalanceInOut"></canvas>
</div>
</q-card-section>
</q-card>
<q-card v-if="chartConfig.showPaymentCountInOut">
<q-card-section class="q-pa-none">
<div style="height: 200px" class="q-pa-sm">
<canvas ref="walletPaymentsInOut"></canvas>
</div>
</q-card-section>
</q-card>
</div>
<div v-if="hasChartActive && !chartDataPointCount">
<q-card>
<q-card-section> No chart data available</q-card-section>
</q-card>
</div>
</div>
</div>

View file

@ -8,52 +8,7 @@
<q-card>
<div class="q-pa-sm q-pl-lg">
<div class="row items-center justify-between q-gutter-xs">
<div class="col">
<div class="float-left">
<q-chip
v-if="searchDate.timeFrom"
removable
@remove="removeCreatedFrom()"
:label="searchDate.timeFrom"
class="ellipsis"
>
</q-chip>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="searchDate.timeFrom" mask="YYYY-MM-DD">
<div class="row">
<q-btn
label="Search"
color="primary"
flat
@click="fetchPayments()"
class="float-left"
v-close-popup
/>
</div>
</q-date>
<q-date v-model="searchDate.timeTo" mask="YYYY-MM-DD">
<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>
<q-chip
removable
v-if="searchDate.timeTo"
@remove="removeCreatedTo()"
:label="searchDate.timeTo"
class="ellipsis"
>
</q-chip>
</div>
</div>
<div class="col"></div>
<div class="float-left">
<q-checkbox
dense
@ -115,7 +70,46 @@
</q-checkbox>
</div>
<q-separator vertical class="q-ma-sm"></q-separator>
<q-btn icon="event" outline flat>
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="searchDate" mask="YYYY-MM-DD" range />
<div class="row">
<div class="col-6">
<q-btn
label="Search"
@click="searchByDate()"
color="primary"
flat
class="float-left"
v-close-popup
/>
</div>
<div class="col-6">
<q-btn
v-close-popup
@click="clearDateSeach()"
label="Clear"
class="float-right"
color="grey"
flat
/>
</div>
</div>
</q-popup-proxy>
<q-badge
v-if="searchDate?.to || searchDate?.from"
class="q-mt-lg q-mr-md"
color="primary"
rounded
floating
style="border-radius: 6px"
/>
</q-btn>
<q-separator vertical class="q-ma-sm"></q-separator>
<div>
<q-btn
v-if="g.user.admin"
@ -214,7 +208,6 @@
:columns="paymentsTable.columns"
v-model:pagination="paymentsTable.pagination"
:filter="paymentsTable.search"
:loading="paymentsTable.loading"
@request="fetchPayments"
>
<template v-slot:header="props">
@ -272,8 +265,8 @@
@click="showDetailsToggle(props.row)"
v-if="props.row.status === 'success'"
size="14px"
:name="props.row.amount < 0 ? 'call_made' : 'call_received'"
:color="props.row.amount < 0 ? 'pink' : 'green'"
:name="props.row.outgoing ? 'call_made' : 'call_received'"
:color="props.row.outgoing ? 'pink' : 'green'"
class="cursor-pointer"
></q-icon>
<q-icon

View file

@ -4,10 +4,7 @@ window.PaymentsPageLogic = {
return {
payments: [],
dailyChartData: [],
searchDate: {
timeFrom: null,
timeTo: null
},
searchDate: {from: null, to: null},
searchData: {
wallet_id: null,
payment_hash: null,
@ -104,7 +101,7 @@ window.PaymentsPageLogic = {
},
search: null,
hideEmpty: true,
loading: true
loading: false
},
chartsReady: false,
showDetails: false,
@ -116,10 +113,6 @@ window.PaymentsPageLogic = {
this.chartsReady = true
await this.$nextTick()
this.initCharts()
this.searchDate.timeFrom = moment()
.subtract(1, 'month')
.format('YYYY-MM-DD')
this.searchDate.timeTo = moment().format('YYYY-MM-DD')
await this.fetchPayments()
},
computed: {},
@ -132,11 +125,11 @@ window.PaymentsPageLogic = {
delete filter['time[ge]']
delete filter['time[le]']
if (this.searchDate.timeFrom) {
filter['time[ge]'] = this.searchDate.timeFrom + 'T00:00:00'
if (this.searchDate.from) {
filter['time[ge]'] = this.searchDate.from + 'T00:00:00'
}
if (this.searchDate.timeTo) {
filter['time[le]'] = this.searchDate.timeTo + 'T23:59:59'
if (this.searchDate.to) {
filter['time[le]'] = this.searchDate.to + 'T23:59:59'
}
this.paymentsTable.filter = filter
@ -156,7 +149,7 @@ window.PaymentsPageLogic = {
p.tag = p.extra.tag
}
p.timeFrom = moment(p.created_at).fromNow()
p.outgoing = p.amount < 0
p.amount =
new Intl.NumberFormat(window.LOCALE).format(p.amount / 1000) +
' sats'
@ -173,7 +166,6 @@ window.PaymentsPageLogic = {
console.error(error)
LNbits.utils.notifyApiError(error)
} finally {
this.paymentsTable.loading = false
this.updateCharts(props)
}
},
@ -183,15 +175,30 @@ window.PaymentsPageLogic = {
}
await this.fetchPayments()
},
clearDateSeach() {
this.searchDate = {from: null, to: null}
delete this.paymentsTable.filter['time[ge]']
delete this.paymentsTable.filter['time[le]']
this.fetchPayments()
},
searchByDate() {
if (typeof this.searchDate === 'string') {
this.searchDate = {
from: this.searchDate,
to: this.searchDate
}
}
if (this.searchDate.from) {
this.paymentsTable.filter['time[ge]'] =
this.searchDate.from + 'T00:00:00'
}
if (this.searchDate.to) {
this.paymentsTable.filter['time[le]'] = this.searchDate.to + 'T23:59:59'
}
async removeCreatedFrom() {
this.searchDate.timeFrom = null
await this.fetchPayments()
},
async removeCreatedTo() {
this.searchDate.timeTo = null
await this.fetchPayments()
this.fetchPayments()
},
showDetailsToggle(payment) {
this.paymentDetails = payment
return (this.showDetails = !this.showDetails)
@ -303,17 +310,17 @@ window.PaymentsPageLogic = {
`/api/v1/payments/stats/daily?${noTimeParams}`
)
const timeFrom = this.searchDate.timeFrom + 'T00:00:00'
const timeTo = this.searchDate.timeTo + 'T00:00:00'
const timeFrom = this.searchDate.from + 'T00:00:00'
const timeTo = this.searchDate.to + 'T23:59:59'
this.lnbitsBalance = data[data.length - 1].balance
data = data.filter(p => {
if (this.searchDate.timeFrom && this.searchDate.timeTo) {
if (this.searchDate.from && this.searchDate.to) {
return p.date >= timeFrom && p.date <= timeTo
}
if (this.searchDate.timeFrom) {
if (this.searchDate.from) {
return p.date >= timeFrom
}
if (this.searchDate.timeTo) {
if (this.searchDate.to) {
return p.date <= timeTo
}
return true

View file

@ -116,6 +116,7 @@ window.WalletPageLogic = {
primaryColor: this.$q.localStorage.getItem('lnbits.primaryColor'),
secondaryColor: this.$q.localStorage.getItem('lnbits.secondaryColor'),
chartData: [],
chartDataPointCount: 0,
chartConfig: {
showBalance: true,
showBalanceInOut: true,
@ -151,6 +152,13 @@ window.WalletPageLogic = {
},
wallet() {
return this.g.wallet
},
hasChartActive() {
return (
this.chartConfig.showBalance ||
this.chartConfig.showBalanceInOut ||
this.chartConfig.showPaymentCountInOut
)
}
},
methods: {
@ -824,11 +832,7 @@ window.WalletPageLogic = {
this.chartConfig = {}
return
}
if (
!this.chartConfig.showBalance &&
!this.chartConfig.showBalanceInOut &&
!this.chartConfig.showPaymentCountInOut
) {
if (!this.hasChartActive) {
return
}
@ -868,6 +872,7 @@ window.WalletPageLogic = {
day: 'numeric'
})
)
this.chartDataPointCount = data.length
return {data, labels}
},
refreshCharts() {
@ -964,12 +969,20 @@ window.WalletPageLogic = {
{
label: 'Balance In',
borderRadius: 5,
data: data.map(s => s.balance_in)
data: data.map(s => s.balance_in),
backgroundColor: LNbits.utils.hexAlpha(
this.primaryColor,
0.3
)
},
{
label: 'Balance Out',
borderRadius: 5,
data: data.map(s => s.balance_out)
data: data.map(s => s.balance_out),
backgroundColor: LNbits.utils.hexAlpha(
this.secondaryColor,
0.3
)
}
]
}
@ -1005,11 +1018,19 @@ window.WalletPageLogic = {
datasets: [
{
label: 'Payments In',
data: data.map(s => s.count_in)
data: data.map(s => s.count_in),
backgroundColor: LNbits.utils.hexAlpha(
this.primaryColor,
0.3
)
},
{
label: 'Payments Out',
data: data.map(s => -s.count_out)
data: data.map(s => -s.count_out),
backgroundColor: LNbits.utils.hexAlpha(
this.secondaryColor,
0.3
)
}
]
}

View file

@ -106,7 +106,7 @@
<span>OFFLINE</span>
</q-badge>
<q-btn-dropdown
v-if="g.user"
v-if="g.user || isUserAuthorized"
flat
rounded
size="sm"