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:
from .crud import update_transaction_status
update_transaction_status(self.payhash, pending)

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

@ -1,5 +1,80 @@
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({
el: '#vue',
mixins: [windowMixin],
@ -31,6 +106,9 @@ new Vue({
pagination: {
rowsPerPage: 10
}
},
transactionsChart: {
show: false
}
};
},
@ -47,7 +125,7 @@ new Vue({
}
},
methods: {
openReceiveDialog: function () {
showReceiveDialog: function () {
this.receive = {
show: true,
status: 'pending',
@ -58,7 +136,7 @@ new Vue({
}
};
},
openSendDialog: function () {
showSendDialog: function () {
this.send = {
show: true,
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 () {
var self = this;
this.receive.status = 'loading';

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

@ -4,7 +4,12 @@
{% block scripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
{{ 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',
'vendor/bolt11/utils.js',
'vendor/bolt11/decoder.js',
@ -26,13 +31,13 @@
<q-btn unelevated
color="purple"
class="full-width"
@click="openSendDialog">Send</q-btn>
@click="showSendDialog">Send</q-btn>
</div>
<div class="col">
<q-btn unelevated
color="deep-purple"
class="full-width"
@click="openReceiveDialog">Receive</q-btn>
@click="showReceiveDialog">Receive</q-btn>
</div>
</div>
</q-card>
@ -45,6 +50,9 @@
</div>
<div class="col-auto">
<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>
<q-table dense flat
@ -67,7 +75,7 @@
<q-td auto-width class="lnbits__q-table__icon-td">
<q-icon size="14px"
: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 key="memo" :props="props">
{{ props.row.memo }}
@ -84,12 +92,6 @@
</q-table>
</q-card-section>
</q-card>
<q-card>
<q-card-section>
<div id="satschart"></div>
</q-card-section>
</q-card>
</div>
<div class="col-12 col-md-4 col-lg-5 q-gutter-y-md">
@ -167,7 +169,7 @@
</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-form v-if="!receive.paymentReq" class="q-gutter-md">
<q-input filled dense
@ -205,7 +207,7 @@
</q-card>
</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-form v-if="!send.invoice" class="q-gutter-md">
<q-input filled dense
@ -249,4 +251,12 @@
</div>
</q-card>
</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 %}

Loading…
Cancel
Save