mirror of
https://github.com/lnbits/lnbits.git
synced 2025-08-02 23:12:34 +02:00
[feat] filter payments in wallet (#2997)
* fix: search payments * fix rogue button * feat: UI polishing * feat: better charts --------- Co-authored-by: Tiago Vasconcelos <talvasconcelos@gmail.com>
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
<q-table :rows="wallets" :columns="walletTable.columns">
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width v-if="g.user.super_user"></q-th>
|
||||
<q-th auto-width></q-th>
|
||||
<q-th
|
||||
auto-width
|
||||
@@ -47,12 +48,14 @@
|
||||
</template>
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td auto-width>
|
||||
<q-td auto-width v-if="g.user.super_user">
|
||||
<lnbits-update-balance
|
||||
:wallet_id="props.row.id"
|
||||
@credit-value="handleBalanceUpdate"
|
||||
class="q-mr-md"
|
||||
></lnbits-update-balance>
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
round
|
||||
icon="menu"
|
||||
|
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -82,6 +82,7 @@ window.localisation.en = {
|
||||
create_invoice: 'Create Invoice',
|
||||
camera_tooltip: 'Use camera to scan an invoice/QR',
|
||||
export_csv: 'Export to CSV',
|
||||
export_csv_details: 'Export to CSV with details',
|
||||
chart_tooltip: 'Show chart',
|
||||
pending: 'Pending',
|
||||
copy_invoice: 'Copy invoice',
|
||||
@@ -539,5 +540,7 @@ window.localisation.en = {
|
||||
reset_wallet_keys_desc:
|
||||
'Reset the API keys for this wallet. This will invalidate the current keys and generate new ones.',
|
||||
view_list: 'View wallets as list',
|
||||
view_column: 'View wallets as rows'
|
||||
view_column: 'View wallets as rows',
|
||||
filter_payments: 'Filter payments',
|
||||
filter_date: 'Filter by date'
|
||||
}
|
||||
|
@@ -359,7 +359,7 @@ window.LNbits = {
|
||||
prepareFilterQuery(tableConfig, props) {
|
||||
if (props) {
|
||||
tableConfig.pagination = props.pagination
|
||||
tableConfig.filter = {...tableConfig.filter, ...props.filter}
|
||||
Object.assign(tableConfig.filter, props.filter)
|
||||
}
|
||||
const pagination = tableConfig.pagination
|
||||
tableConfig.loading = true
|
||||
|
@@ -595,7 +595,6 @@ window.app.component('username-password', {
|
||||
},
|
||||
async signInWithNostr() {
|
||||
try {
|
||||
console.log('### signInWithNostr')
|
||||
const nostrToken = await this.createNostrToken()
|
||||
if (!nostrToken) {
|
||||
return
|
||||
|
@@ -6,7 +6,6 @@ window.app.component('payment-list', {
|
||||
data() {
|
||||
return {
|
||||
denomination: LNBITS_DENOMINATION,
|
||||
failedPaymentsToggle: false,
|
||||
payments: [],
|
||||
paymentsTable: {
|
||||
columns: [
|
||||
@@ -39,6 +38,13 @@ window.app.component('payment-list', {
|
||||
loading: false
|
||||
},
|
||||
searchDate: {from: null, to: null},
|
||||
searchStatus: {
|
||||
success: true,
|
||||
pending: true,
|
||||
failed: false,
|
||||
incoming: true,
|
||||
outgoing: true
|
||||
},
|
||||
exportTagName: '',
|
||||
exportPaymentTagList: [],
|
||||
paymentsCSV: {
|
||||
@@ -263,18 +269,40 @@ window.app.component('payment-list', {
|
||||
console.error(e)
|
||||
return `${amount} ???`
|
||||
}
|
||||
},
|
||||
handleFilterChanged() {
|
||||
const {success, pending, failed, incoming, outgoing} = this.searchStatus
|
||||
|
||||
delete this.paymentsTable.filter['status[ne]']
|
||||
delete this.paymentsTable.filter['status[eq]']
|
||||
if (success && pending && failed) {
|
||||
// No status filter
|
||||
} else if (success && pending) {
|
||||
this.paymentsTable.filter['status[ne]'] = 'failed'
|
||||
} else if (success && failed) {
|
||||
this.paymentsTable.filter['status[ne]'] = 'pending'
|
||||
} else if (failed && pending) {
|
||||
this.paymentsTable.filter['status[ne]'] = 'success'
|
||||
} else if (success) {
|
||||
this.paymentsTable.filter['status[eq]'] = 'success'
|
||||
} else if (pending) {
|
||||
this.paymentsTable.filter['status[eq]'] = 'pending'
|
||||
} else if (failed) {
|
||||
this.paymentsTable.filter['status[eq]'] = 'failed'
|
||||
}
|
||||
|
||||
delete this.paymentsTable.filter['amount[ge]']
|
||||
delete this.paymentsTable.filter['amount[le]']
|
||||
if (incoming && outgoing) {
|
||||
// do nothing
|
||||
} else if (incoming) {
|
||||
this.paymentsTable.filter['amount[ge]'] = 0
|
||||
} else if (outgoing) {
|
||||
this.paymentsTable.filter['amount[le]'] = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
failedPaymentsToggle(newVal) {
|
||||
if (newVal === false) {
|
||||
this.paymentsTable.filter['status[ne]'] = 'failed'
|
||||
} else {
|
||||
delete this.paymentsTable.filter['status[ne]']
|
||||
}
|
||||
this.paymentsTable.pagination.page = 1
|
||||
this.fetchPayments()
|
||||
},
|
||||
'paymentsTable.search': {
|
||||
handler() {
|
||||
const props = {}
|
||||
|
@@ -352,9 +352,6 @@ window.UsersPageLogic = {
|
||||
})
|
||||
.catch(LNbits.utils.notifyApiError)
|
||||
},
|
||||
exportUsers() {
|
||||
console.log('export users')
|
||||
},
|
||||
async showAccountPage(user_id) {
|
||||
this.activeUser.showPassword = false
|
||||
this.activeUser.showUserId = false
|
||||
|
@@ -854,7 +854,9 @@ window.WalletPageLogic = {
|
||||
handleFilterChange(value = {}) {
|
||||
if (
|
||||
this.paymentsFilter['time[ge]'] !== value['time[ge]'] ||
|
||||
this.paymentsFilter['time[le]'] !== value['time[le]']
|
||||
this.paymentsFilter['time[le]'] !== value['time[le]'] ||
|
||||
this.paymentsFilter['amount[ge]'] !== value['amount[ge]'] ||
|
||||
this.paymentsFilter['amount[le]'] !== value['amount[le]']
|
||||
) {
|
||||
this.refreshCharts()
|
||||
}
|
||||
@@ -884,6 +886,19 @@ window.WalletPageLogic = {
|
||||
filterChartData(data) {
|
||||
const timeFrom = this.paymentsFilter['time[ge]'] + 'T00:00:00'
|
||||
const timeTo = this.paymentsFilter['time[le]'] + 'T23:59:59'
|
||||
|
||||
let totalBalance = 0
|
||||
data = data.map(p => {
|
||||
if (this.paymentsFilter['amount[ge]'] !== undefined) {
|
||||
totalBalance += p.balance_in
|
||||
return {...p, balance: totalBalance, balance_out: 0, count_out: 0}
|
||||
}
|
||||
if (this.paymentsFilter['amount[le]'] !== undefined) {
|
||||
totalBalance -= p.balance_out
|
||||
return {...p, balance: totalBalance, balance_in: 0, count_in: 0}
|
||||
}
|
||||
return {...p}
|
||||
})
|
||||
data = data.filter(p => {
|
||||
if (
|
||||
this.paymentsFilter['time[ge]'] &&
|
||||
@@ -899,6 +914,7 @@ window.WalletPageLogic = {
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const labels = data.map(s =>
|
||||
new Date(s.date).toLocaleString('default', {
|
||||
month: 'short',
|
||||
|
@@ -419,7 +419,6 @@
|
||||
dense
|
||||
use-input
|
||||
use-chips
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
></q-select>
|
||||
<div v-else-if="o.type === 'bool'">
|
||||
@@ -639,16 +638,100 @@
|
||||
</q-input>
|
||||
</div>
|
||||
<div class="gt-sm col-auto">
|
||||
<q-btn icon="event" flat color="grey">
|
||||
<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-badge>
|
||||
<q-tooltip>
|
||||
<span v-text="$t('filter_date')"></span>
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn color="grey" icon="filter_alt" flat>
|
||||
<q-menu>
|
||||
<q-item dense>
|
||||
<q-checkbox
|
||||
v-model="searchStatus.success"
|
||||
@click="handleFilterChanged"
|
||||
label="Success Payments"
|
||||
></q-checkbox>
|
||||
</q-item>
|
||||
<q-item dense>
|
||||
<q-checkbox
|
||||
v-model="searchStatus.pending"
|
||||
@click="handleFilterChanged"
|
||||
label="Pending Payments"
|
||||
></q-checkbox>
|
||||
</q-item>
|
||||
<q-item dense>
|
||||
<q-checkbox
|
||||
v-model="searchStatus.failed"
|
||||
@click="handleFilterChanged"
|
||||
label="Failed Payments"
|
||||
></q-checkbox>
|
||||
</q-item>
|
||||
<q-separator></q-separator>
|
||||
<q-item dense>
|
||||
<q-checkbox
|
||||
v-model="searchStatus.incoming"
|
||||
@click="handleFilterChanged"
|
||||
label="Incoming Payments"
|
||||
></q-checkbox>
|
||||
</q-item>
|
||||
<q-item dense>
|
||||
<q-checkbox
|
||||
v-model="searchStatus.outgoing"
|
||||
@click="handleFilterChanged"
|
||||
label="Outgoing Payments"
|
||||
></q-checkbox>
|
||||
</q-item>
|
||||
</q-menu>
|
||||
<q-tooltip>
|
||||
<span v-text="$t('filter_payments')"></span>
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn-dropdown
|
||||
dense
|
||||
outline
|
||||
persistent
|
||||
dense
|
||||
icon="archive"
|
||||
split
|
||||
class="q-mr-sm"
|
||||
color="grey"
|
||||
label="Export"
|
||||
split
|
||||
@click="exportCSV(false)"
|
||||
>
|
||||
<q-tooltip>
|
||||
<span v-text="$t('export_csv')"></span>
|
||||
</q-tooltip>
|
||||
<q-list>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
@@ -688,59 +771,12 @@
|
||||
outline
|
||||
color="grey"
|
||||
@click="exportCSV(true)"
|
||||
label="Export to CSV with details"
|
||||
:label="$t('export_csv_details')"
|
||||
></q-btn>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
<q-btn icon="event" outline flat color="grey">
|
||||
<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-checkbox
|
||||
v-model="failedPaymentsToggle"
|
||||
checked-icon="warning"
|
||||
unchecked-icon="warning_off"
|
||||
:color="failedPaymentsToggle ? 'yellow' : 'grey'"
|
||||
size="xs"
|
||||
>
|
||||
<q-tooltip>
|
||||
<span v-text="`Include failed payments`"></span>
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-my-md"></div>
|
||||
|
Reference in New Issue
Block a user