diff --git a/apps/core/static/css/skeleton-tabs.css b/apps/core/static/css/skeleton-tabs.css new file mode 100644 index 0000000..50819e4 --- /dev/null +++ b/apps/core/static/css/skeleton-tabs.css @@ -0,0 +1,29 @@ +/* https://github.com/nathancahill/skeleton-tabs */ +ul.tab-nav { + list-style: none; + border-bottom: 1px solid #bbb; + padding-left: 5px; +} + +ul.tab-nav li { + display: inline; +} + +ul.tab-nav li a.button { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + margin-bottom: -1px; + border-bottom: none; +} + +ul.tab-nav li a.active.button { + border-bottom: 0.175em solid #fff; +} + +.tab-content .tab-pane { + display: none; +} + +.tab-content .tab-pane.active { + display: block; +} diff --git a/apps/core/static/js/skeleton-tabs.js b/apps/core/static/js/skeleton-tabs.js new file mode 100644 index 0000000..27b1360 --- /dev/null +++ b/apps/core/static/js/skeleton-tabs.js @@ -0,0 +1,22 @@ +/* https://github.com/nathancahill/skeleton-tabs */ +(function() { + function main() { + var tabButtons = [].slice.call(document.querySelectorAll('ul.tab-nav li a.button')); + + tabButtons.map(function(button) { + button.addEventListener('click', function() { + document.querySelector('li a.active.button').classList.remove('active'); + button.classList.add('active'); + + document.querySelector('.tab-pane.active').classList.remove('active'); + document.querySelector(button.getAttribute('href')).classList.add('active'); + }) + }) + } + + if (document.readyState !== 'loading') { + main(); + } else { + document.addEventListener('DOMContentLoaded', main); + } +})(); diff --git a/apps/core/templates/base.html b/apps/core/templates/base.html index 7cbc06b..13d42b1 100644 --- a/apps/core/templates/base.html +++ b/apps/core/templates/base.html @@ -8,6 +8,8 @@ + +
{% if user.is_authenticated %} diff --git a/apps/monitor/graph.py b/apps/monitor/graph.py new file mode 100644 index 0000000..b923280 --- /dev/null +++ b/apps/monitor/graph.py @@ -0,0 +1,96 @@ +from django.db import connection +import datetime +import matplotlib.pyplot as plt +from io import StringIO +from matplotlib.backends.backend_agg import FigureCanvasAgg +from matplotlib.figure import Figure +import matplotlib.ticker as plticker +from django.http import HttpResponse + +class Graph: + + def graph_days(self, Crypto, Fiat, DayDiff): + + x = [] + y = [] + + with connection.cursor() as cursor: + sql = """SELECT date(datetime_valid), rate FROM + (select date(datetime_valid) as day, max(datetime_valid) as last + from exchangerate WHERE crypto_currency = %s AND fiat_currency = %s + AND datetime_valid >= %s + GROUP BY day + ORDER BY datetime_valid DESC) AS a + JOIN exchangerate AS b ON a.last = b.datetime_valid + AND crypto_currency = %s AND fiat_currency = %s + ORDER BY datetime_valid ASC""" + startDate = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) - datetime.timedelta(days=int(DayDiff)) + cursor.execute(sql, [Crypto, Fiat, startDate, Crypto, Fiat]) + rows = cursor.fetchall() + for row in rows: + x.append(datetime.datetime.strptime(row[0], '%Y-%m-%d')) + y.append(row[1]) + + if len(x) == 0: + raise Exception("no data for this time range in the database") + + fig_size = plt.rcParams["figure.figsize"] + fig_size[0] = 5 + fig_size[1] = 4 + plt.rcParams["figure.figsize"] = fig_size + + fig = Figure() + ax = fig.add_subplot(1, 1, 1) + + ax.plot(x, y, color='green', linestyle='dashed', linewidth = 2, + marker='o', markerfacecolor='blue', markersize=2) + + loc = plticker.MultipleLocator(base=(len(x)/4.0)) + ax.xaxis.set_major_locator(loc) + + ax.set_xlabel("time") + ax.set_ylabel(Fiat) + ax.set_title(('%s in %s' % (Crypto, Fiat))) + + response = HttpResponse(content_type = 'image/png') + canvas = FigureCanvasAgg(fig) + canvas.print_png(response) + return response + + def graph_hours(self, Crypto, Fiat, HourDiff): + + x = [] + y = [] + + with connection.cursor() as cursor: + sql = """SELECT datetime_valid, rate FROM exchangerate + WHERE crypto_currency = %s AND fiat_currency = %s + AND datetime_valid >= %s + ORDER BY datetime_valid ASC""" + startDate = datetime.datetime.today() - datetime.timedelta(hours=int(HourDiff)) + cursor.execute(sql, [Crypto, Fiat, startDate]) + rows = cursor.fetchall() + for row in rows: + x.append(row[0]) + y.append(row[1]) + + if len(x) == 0: + raise Exception("no data for this time range in the database") + + fig = Figure() + ax = fig.add_subplot(1, 1, 1) + + ax.plot(x, y, color='green', linestyle='dashed', linewidth = 2, + marker='o', markerfacecolor='blue', markersize=2) + + loc = plticker.MultipleLocator(base=(len(x)/5.0)) + ax.xaxis.set_major_locator(loc) + + ax.set_xlabel("time") + ax.set_ylabel(Fiat) + ax.set_title(('%s in %s' % (Crypto, Fiat))) + + response = HttpResponse(content_type = 'image/png') + canvas = FigureCanvasAgg(fig) + canvas.print_png(response) + return response diff --git a/apps/monitor/templates/monitor.html b/apps/monitor/templates/monitor.html index febac7d..50d5652 100644 --- a/apps/monitor/templates/monitor.html +++ b/apps/monitor/templates/monitor.html @@ -3,6 +3,7 @@ {% block content %}Hint: these numbers are not very accurate.
{% for c in cryptos %} @@ -29,6 +30,7 @@ {% if c.bought_tax_free %} We can sell without paying taxes: {{ c.bought_tax_free|floatformat:3 }} {{ c.crypto }} for {{ c.value_tax_free|floatformat:2 }} EUR