Chart polish (#2973)
This commit is contained in:
parent
60de308c8f
commit
c08623277e
7 changed files with 170 additions and 130 deletions
|
|
@ -440,6 +440,8 @@ async def get_payments_daily_stats(
|
||||||
balance_total: float = 0
|
balance_total: float = 0
|
||||||
|
|
||||||
_none = PaymentDailyStats(date=datetime.now(timezone.utc))
|
_none = PaymentDailyStats(date=datetime.now(timezone.utc))
|
||||||
|
if len(data_in) == 0 and len(data_out) == 0:
|
||||||
|
return []
|
||||||
if len(data_in) == 0:
|
if len(data_in) == 0:
|
||||||
data_in = [_none]
|
data_in = [_none]
|
||||||
if len(data_out) == 0:
|
if len(data_out) == 0:
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,12 @@
|
||||||
<!---->
|
<!---->
|
||||||
{% block scripts %} {{ window_vars(user) }}{% endblock %} {% block page %}
|
{% block scripts %} {{ window_vars(user) }}{% endblock %} {% block page %}
|
||||||
|
|
||||||
<div class="row q-col-gutter-md">
|
<div class="row q-col-gutter-md q-mb-md">
|
||||||
<div v-if="user" class="col-md-12 col-lg-6 q-gutter-y-md">
|
<div class="col-12">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<div>
|
||||||
<div class="row">
|
<div class="q-gutter-y-md">
|
||||||
<div class="col">
|
<q-tabs v-model="tab" align="left">
|
||||||
<q-tabs v-model="tab" align="justify">
|
|
||||||
<q-tab
|
<q-tab
|
||||||
name="user"
|
name="user"
|
||||||
:label="$t('account_settings')"
|
:label="$t('account_settings')"
|
||||||
|
|
@ -27,11 +26,21 @@
|
||||||
@update="val => tab = val.name"
|
@update="val => tab = val.name"
|
||||||
></q-tab>
|
></q-tab>
|
||||||
</q-tabs>
|
</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-tab-panels v-model="tab">
|
<q-tab-panels v-model="tab">
|
||||||
<q-tab-panel name="user">
|
<q-tab-panel name="user">
|
||||||
<div v-if="credentialsData.show">
|
<div v-if="credentialsData.show">
|
||||||
<q-separator></q-separator>
|
|
||||||
|
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
|
@ -132,11 +141,10 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<q-card-section>
|
<q-card-section v-if="user.extra.picture">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-img
|
<q-img
|
||||||
v-if="user.extra.picture"
|
|
||||||
style="max-width: 100px"
|
style="max-width: 100px"
|
||||||
:src="user.extra.picture"
|
:src="user.extra.picture"
|
||||||
class="float-right"
|
class="float-right"
|
||||||
|
|
@ -144,7 +152,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-separator></q-separator>
|
|
||||||
|
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,10 @@
|
||||||
>{% endfor %}
|
>{% endfor %}
|
||||||
</q-card>
|
</q-card>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div
|
||||||
|
v-show="chartDataPointCount"
|
||||||
|
class="col-12 col-md-5 q-gutter-y-md"
|
||||||
|
>
|
||||||
<q-card v-if="chartConfig.showBalance">
|
<q-card v-if="chartConfig.showBalance">
|
||||||
<q-card-section class="q-pa-none">
|
<q-card-section class="q-pa-none">
|
||||||
<div style="height: 200px" class="q-pa-sm">
|
<div style="height: 200px" class="q-pa-sm">
|
||||||
|
|
@ -503,6 +507,12 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="hasChartActive && !chartDataPointCount">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section> No chart data available</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-dialog v-model="icon.show" position="top">
|
<q-dialog v-model="icon.show" position="top">
|
||||||
|
|
|
||||||
|
|
@ -8,52 +8,7 @@
|
||||||
<q-card>
|
<q-card>
|
||||||
<div class="q-pa-sm q-pl-lg">
|
<div class="q-pa-sm q-pl-lg">
|
||||||
<div class="row items-center justify-between q-gutter-xs">
|
<div class="row items-center justify-between q-gutter-xs">
|
||||||
<div class="col">
|
<div class="col"></div>
|
||||||
<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="float-left">
|
<div class="float-left">
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
dense
|
dense
|
||||||
|
|
@ -115,7 +70,46 @@
|
||||||
</q-checkbox>
|
</q-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<q-separator vertical class="q-ma-sm"></q-separator>
|
<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>
|
<div>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="g.user.admin"
|
v-if="g.user.admin"
|
||||||
|
|
@ -214,7 +208,6 @@
|
||||||
:columns="paymentsTable.columns"
|
:columns="paymentsTable.columns"
|
||||||
v-model:pagination="paymentsTable.pagination"
|
v-model:pagination="paymentsTable.pagination"
|
||||||
:filter="paymentsTable.search"
|
:filter="paymentsTable.search"
|
||||||
:loading="paymentsTable.loading"
|
|
||||||
@request="fetchPayments"
|
@request="fetchPayments"
|
||||||
>
|
>
|
||||||
<template v-slot:header="props">
|
<template v-slot:header="props">
|
||||||
|
|
@ -272,8 +265,8 @@
|
||||||
@click="showDetailsToggle(props.row)"
|
@click="showDetailsToggle(props.row)"
|
||||||
v-if="props.row.status === 'success'"
|
v-if="props.row.status === 'success'"
|
||||||
size="14px"
|
size="14px"
|
||||||
:name="props.row.amount < 0 ? 'call_made' : 'call_received'"
|
:name="props.row.outgoing ? 'call_made' : 'call_received'"
|
||||||
:color="props.row.amount < 0 ? 'pink' : 'green'"
|
:color="props.row.outgoing ? 'pink' : 'green'"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
></q-icon>
|
></q-icon>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ window.PaymentsPageLogic = {
|
||||||
return {
|
return {
|
||||||
payments: [],
|
payments: [],
|
||||||
dailyChartData: [],
|
dailyChartData: [],
|
||||||
searchDate: {
|
searchDate: {from: null, to: null},
|
||||||
timeFrom: null,
|
|
||||||
timeTo: null
|
|
||||||
},
|
|
||||||
searchData: {
|
searchData: {
|
||||||
wallet_id: null,
|
wallet_id: null,
|
||||||
payment_hash: null,
|
payment_hash: null,
|
||||||
|
|
@ -104,7 +101,7 @@ window.PaymentsPageLogic = {
|
||||||
},
|
},
|
||||||
search: null,
|
search: null,
|
||||||
hideEmpty: true,
|
hideEmpty: true,
|
||||||
loading: true
|
loading: false
|
||||||
},
|
},
|
||||||
chartsReady: false,
|
chartsReady: false,
|
||||||
showDetails: false,
|
showDetails: false,
|
||||||
|
|
@ -116,10 +113,6 @@ window.PaymentsPageLogic = {
|
||||||
this.chartsReady = true
|
this.chartsReady = true
|
||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
this.initCharts()
|
this.initCharts()
|
||||||
this.searchDate.timeFrom = moment()
|
|
||||||
.subtract(1, 'month')
|
|
||||||
.format('YYYY-MM-DD')
|
|
||||||
this.searchDate.timeTo = moment().format('YYYY-MM-DD')
|
|
||||||
await this.fetchPayments()
|
await this.fetchPayments()
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
|
|
@ -132,11 +125,11 @@ window.PaymentsPageLogic = {
|
||||||
|
|
||||||
delete filter['time[ge]']
|
delete filter['time[ge]']
|
||||||
delete filter['time[le]']
|
delete filter['time[le]']
|
||||||
if (this.searchDate.timeFrom) {
|
if (this.searchDate.from) {
|
||||||
filter['time[ge]'] = this.searchDate.timeFrom + 'T00:00:00'
|
filter['time[ge]'] = this.searchDate.from + 'T00:00:00'
|
||||||
}
|
}
|
||||||
if (this.searchDate.timeTo) {
|
if (this.searchDate.to) {
|
||||||
filter['time[le]'] = this.searchDate.timeTo + 'T23:59:59'
|
filter['time[le]'] = this.searchDate.to + 'T23:59:59'
|
||||||
}
|
}
|
||||||
this.paymentsTable.filter = filter
|
this.paymentsTable.filter = filter
|
||||||
|
|
||||||
|
|
@ -156,7 +149,7 @@ window.PaymentsPageLogic = {
|
||||||
p.tag = p.extra.tag
|
p.tag = p.extra.tag
|
||||||
}
|
}
|
||||||
p.timeFrom = moment(p.created_at).fromNow()
|
p.timeFrom = moment(p.created_at).fromNow()
|
||||||
|
p.outgoing = p.amount < 0
|
||||||
p.amount =
|
p.amount =
|
||||||
new Intl.NumberFormat(window.LOCALE).format(p.amount / 1000) +
|
new Intl.NumberFormat(window.LOCALE).format(p.amount / 1000) +
|
||||||
' sats'
|
' sats'
|
||||||
|
|
@ -173,7 +166,6 @@ window.PaymentsPageLogic = {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
} finally {
|
} finally {
|
||||||
this.paymentsTable.loading = false
|
|
||||||
this.updateCharts(props)
|
this.updateCharts(props)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -183,15 +175,30 @@ window.PaymentsPageLogic = {
|
||||||
}
|
}
|
||||||
await this.fetchPayments()
|
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.fetchPayments()
|
||||||
this.searchDate.timeFrom = null
|
|
||||||
await this.fetchPayments()
|
|
||||||
},
|
|
||||||
async removeCreatedTo() {
|
|
||||||
this.searchDate.timeTo = null
|
|
||||||
await this.fetchPayments()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showDetailsToggle(payment) {
|
showDetailsToggle(payment) {
|
||||||
this.paymentDetails = payment
|
this.paymentDetails = payment
|
||||||
return (this.showDetails = !this.showDetails)
|
return (this.showDetails = !this.showDetails)
|
||||||
|
|
@ -303,17 +310,17 @@ window.PaymentsPageLogic = {
|
||||||
`/api/v1/payments/stats/daily?${noTimeParams}`
|
`/api/v1/payments/stats/daily?${noTimeParams}`
|
||||||
)
|
)
|
||||||
|
|
||||||
const timeFrom = this.searchDate.timeFrom + 'T00:00:00'
|
const timeFrom = this.searchDate.from + 'T00:00:00'
|
||||||
const timeTo = this.searchDate.timeTo + 'T00:00:00'
|
const timeTo = this.searchDate.to + 'T23:59:59'
|
||||||
this.lnbitsBalance = data[data.length - 1].balance
|
this.lnbitsBalance = data[data.length - 1].balance
|
||||||
data = data.filter(p => {
|
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
|
return p.date >= timeFrom && p.date <= timeTo
|
||||||
}
|
}
|
||||||
if (this.searchDate.timeFrom) {
|
if (this.searchDate.from) {
|
||||||
return p.date >= timeFrom
|
return p.date >= timeFrom
|
||||||
}
|
}
|
||||||
if (this.searchDate.timeTo) {
|
if (this.searchDate.to) {
|
||||||
return p.date <= timeTo
|
return p.date <= timeTo
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ window.WalletPageLogic = {
|
||||||
primaryColor: this.$q.localStorage.getItem('lnbits.primaryColor'),
|
primaryColor: this.$q.localStorage.getItem('lnbits.primaryColor'),
|
||||||
secondaryColor: this.$q.localStorage.getItem('lnbits.secondaryColor'),
|
secondaryColor: this.$q.localStorage.getItem('lnbits.secondaryColor'),
|
||||||
chartData: [],
|
chartData: [],
|
||||||
|
chartDataPointCount: 0,
|
||||||
chartConfig: {
|
chartConfig: {
|
||||||
showBalance: true,
|
showBalance: true,
|
||||||
showBalanceInOut: true,
|
showBalanceInOut: true,
|
||||||
|
|
@ -151,6 +152,13 @@ window.WalletPageLogic = {
|
||||||
},
|
},
|
||||||
wallet() {
|
wallet() {
|
||||||
return this.g.wallet
|
return this.g.wallet
|
||||||
|
},
|
||||||
|
hasChartActive() {
|
||||||
|
return (
|
||||||
|
this.chartConfig.showBalance ||
|
||||||
|
this.chartConfig.showBalanceInOut ||
|
||||||
|
this.chartConfig.showPaymentCountInOut
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -824,11 +832,7 @@ window.WalletPageLogic = {
|
||||||
this.chartConfig = {}
|
this.chartConfig = {}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (!this.hasChartActive) {
|
||||||
!this.chartConfig.showBalance &&
|
|
||||||
!this.chartConfig.showBalanceInOut &&
|
|
||||||
!this.chartConfig.showPaymentCountInOut
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -868,6 +872,7 @@ window.WalletPageLogic = {
|
||||||
day: 'numeric'
|
day: 'numeric'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
this.chartDataPointCount = data.length
|
||||||
return {data, labels}
|
return {data, labels}
|
||||||
},
|
},
|
||||||
refreshCharts() {
|
refreshCharts() {
|
||||||
|
|
@ -964,12 +969,20 @@ window.WalletPageLogic = {
|
||||||
{
|
{
|
||||||
label: 'Balance In',
|
label: 'Balance In',
|
||||||
borderRadius: 5,
|
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',
|
label: 'Balance Out',
|
||||||
borderRadius: 5,
|
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: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: 'Payments In',
|
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',
|
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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
<span>OFFLINE</span>
|
<span>OFFLINE</span>
|
||||||
</q-badge>
|
</q-badge>
|
||||||
<q-btn-dropdown
|
<q-btn-dropdown
|
||||||
v-if="g.user"
|
v-if="g.user || isUserAuthorized"
|
||||||
flat
|
flat
|
||||||
rounded
|
rounded
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue