Browse Source

chore: initial version of tx chart

fee_issues
Eneko Illarramendi 5 years ago
parent
commit
9382381144
  1. 1
      lnbits/core/models.py
  2. 88
      lnbits/core/static/js/wallet.js
  3. 32
      lnbits/core/templates/core/wallet.html

1
lnbits/core/models.py

@ -59,4 +59,5 @@ class Transaction(NamedTuple):
def set_pending(self, pending: bool) -> None: def set_pending(self, pending: bool) -> None:
from .crud import update_transaction_status from .crud import update_transaction_status
update_transaction_status(self.payhash, pending) update_transaction_status(self.payhash, pending)

88
lnbits/core/static/js/wallet.js

@ -1,5 +1,80 @@
Vue.component(VueQrcode.name, VueQrcode); Vue.component(VueQrcode.name, VueQrcode);
function generateChart(canvas, transactions) {
var txs = [];
var n = 0;
var data = {
labels: [],
sats: [],
cumulative: []
};
_.each(transactions.sort(function (a, b) {
return a.time - b.time;
}), function (tx) {
txs.push({
day: Quasar.utils.date.formatDate(tx.date, 'YYYY-MM-DDTHH:00'),
sat: tx.sat,
});
});
_.each(_.groupBy(txs, 'day'), function (value, day) {
var sat = _.reduce(value, function(memo, tx) { return memo + tx.sat; }, 0);
n = n + sat;
data.labels.push(day);
data.sats.push(sat);
data.cumulative.push(n);
});
new Chart(canvas.getContext('2d'), {
type: 'bar',
data: {
labels: data.labels,
datasets: [
{
data: data.cumulative,
type: 'line',
label: 'balance',
borderColor: '#673ab7', // deep-purple
borderWidth: 4,
pointRadius: 3,
fill: false
},
{
data: data.sats,
type: 'bar',
label: 'tx',
backgroundColor: function (ctx) {
var value = ctx.dataset.data[ctx.dataIndex];
return (value < 0) ? '#e91e63' : '#4caf50'; // pink : green
}
}
]
},
options: {
title: {
text: 'Chart.js Combo Time Scale'
},
tooltips: {
mode: 'index',
intersect:false
},
scales: {
xAxes: [{
type: 'time',
display: true,
time: {
minUnit: 'hour',
stepSize: 3
}
}],
},
}
});
}
new Vue({ new Vue({
el: '#vue', el: '#vue',
mixins: [windowMixin], mixins: [windowMixin],
@ -31,6 +106,9 @@ new Vue({
pagination: { pagination: {
rowsPerPage: 10 rowsPerPage: 10
} }
},
transactionsChart: {
show: false
} }
}; };
}, },
@ -47,7 +125,7 @@ new Vue({
} }
}, },
methods: { methods: {
openReceiveDialog: function () { showReceiveDialog: function () {
this.receive = { this.receive = {
show: true, show: true,
status: 'pending', status: 'pending',
@ -58,7 +136,7 @@ new Vue({
} }
}; };
}, },
openSendDialog: function () { showSendDialog: function () {
this.send = { this.send = {
show: true, show: true,
invoice: null, invoice: null,
@ -67,6 +145,12 @@ new Vue({
} }
}; };
}, },
showChart: function () {
this.transactionsChart.show = true;
this.$nextTick(function () {
generateChart(this.$refs.canvas, this.transactions);
});
},
createInvoice: function () { createInvoice: function () {
var self = this; var self = this;
this.receive.status = 'loading'; this.receive.status = 'loading';

32
lnbits/core/templates/core/wallet.html

@ -4,7 +4,12 @@
{% block scripts %} {% block scripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
{{ window_vars(user, wallet) }} {{ window_vars(user, wallet) }}
{% assets filters='rjsmin', output='__bundle__/core/chart.js',
'vendor/chart.js@2.9.3/chart.min.js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets filters='rjsmin', output='__bundle__/core/wallet.js', {% assets filters='rjsmin', output='__bundle__/core/wallet.js',
'vendor/bolt11/utils.js', 'vendor/bolt11/utils.js',
'vendor/bolt11/decoder.js', 'vendor/bolt11/decoder.js',
@ -26,13 +31,13 @@
<q-btn unelevated <q-btn unelevated
color="purple" color="purple"
class="full-width" class="full-width"
@click="openSendDialog">Send</q-btn> @click="showSendDialog">Send</q-btn>
</div> </div>
<div class="col"> <div class="col">
<q-btn unelevated <q-btn unelevated
color="deep-purple" color="deep-purple"
class="full-width" class="full-width"
@click="openReceiveDialog">Receive</q-btn> @click="showReceiveDialog">Receive</q-btn>
</div> </div>
</div> </div>
</q-card> </q-card>
@ -45,6 +50,9 @@
</div> </div>
<div class="col-auto"> <div class="col-auto">
<q-btn flat color="grey" onclick="exportbut()">Export to CSV</q-btn> <q-btn flat color="grey" onclick="exportbut()">Export to CSV</q-btn>
<q-btn dense flat round icon="show_chart" color="grey" @click="showChart">
<q-tooltip>Show chart</q-tooltip>
</q-btn>
</div> </div>
</div> </div>
<q-table dense flat <q-table dense flat
@ -67,7 +75,7 @@
<q-td auto-width class="lnbits__q-table__icon-td"> <q-td auto-width class="lnbits__q-table__icon-td">
<q-icon size="14px" <q-icon size="14px"
:name="(props.row.sat < 0) ? 'call_made' : 'call_received'" :name="(props.row.sat < 0) ? 'call_made' : 'call_received'"
:color="(props.row.sat < 0) ? 'purple-5' : 'green'"></q-icon> :color="(props.row.sat < 0) ? 'pink' : 'green'"></q-icon>
</q-td> </q-td>
<q-td key="memo" :props="props"> <q-td key="memo" :props="props">
{{ props.row.memo }} {{ props.row.memo }}
@ -84,12 +92,6 @@
</q-table> </q-table>
</q-card-section> </q-card-section>
</q-card> </q-card>
<q-card>
<q-card-section>
<div id="satschart"></div>
</q-card-section>
</q-card>
</div> </div>
<div class="col-12 col-md-4 col-lg-5 q-gutter-y-md"> <div class="col-12 col-md-4 col-lg-5 q-gutter-y-md">
@ -167,7 +169,7 @@
</div> </div>
</div> </div>
<q-dialog v-model="receive.show" :position="($q.screen.gt.sm) ? 'standard' : 'top'"> <q-dialog v-model="receive.show" position="top">
<q-card class="q-pa-md" style="width: 500px"> <q-card class="q-pa-md" style="width: 500px">
<q-form v-if="!receive.paymentReq" class="q-gutter-md"> <q-form v-if="!receive.paymentReq" class="q-gutter-md">
<q-input filled dense <q-input filled dense
@ -205,7 +207,7 @@
</q-card> </q-card>
</q-dialog> </q-dialog>
<q-dialog v-model="send.show" :position="($q.screen.gt.sm) ? 'standard' : 'top'"> <q-dialog v-model="send.show" position="top">
<q-card class="q-pa-md" style="width: 500px"> <q-card class="q-pa-md" style="width: 500px">
<q-form v-if="!send.invoice" class="q-gutter-md"> <q-form v-if="!send.invoice" class="q-gutter-md">
<q-input filled dense <q-input filled dense
@ -249,4 +251,12 @@
</div> </div>
</q-card> </q-card>
</q-dialog> </q-dialog>
<q-dialog v-model="transactionsChart.show" position="top">
<q-card class="q-pa-md" style="width: 800px; max-width: unset">
<q-card-section>
<canvas ref="canvas" width="600" height="400"></canvas>
</q-card-section>
</q-card>
</q-dialog>
{% endblock %} {% endblock %}

Loading…
Cancel
Save