Added money conversion feature
This commit is contained in:
parent
0babc78d63
commit
0431feba3b
|
@ -1,10 +1,17 @@
|
|||
# coding: utf-8
|
||||
|
||||
# amiibo
|
||||
from .models import Collection
|
||||
from .models import Collection, AmiiboPrice
|
||||
|
||||
|
||||
def collections(request):
|
||||
return {
|
||||
'collections': Collection.objects.all().order_by('name_eu')
|
||||
'COLLECTIONS': Collection.objects.all().order_by('name_eu')
|
||||
}
|
||||
|
||||
|
||||
def currencies(request):
|
||||
return {
|
||||
'CURRENCIES': AmiiboPrice.objects.all().distinct('currency')\
|
||||
.values_list('currency', flat=True)
|
||||
}
|
||||
|
|
|
@ -11,3 +11,10 @@ def debug(request):
|
|||
return {
|
||||
'DEBUG': settings.DEBUG,
|
||||
}
|
||||
|
||||
|
||||
def files(request):
|
||||
return {
|
||||
'MEDIA_URL': settings.MEDIA_URL,
|
||||
'STATIC_URL': settings.STATIC_URL,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# coding: utf-8
|
||||
|
||||
# python
|
||||
from __future__ import unicode_literals
|
||||
import json
|
||||
import os
|
||||
|
||||
# third party
|
||||
import requests
|
||||
|
||||
# django
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
# amiibo
|
||||
from amiibofindr.apps.amiibo.models import AmiiboPrice
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@property
|
||||
def rates_url(self):
|
||||
return 'https://openexchangerates.org/api/latest.json?app_id={}'.format(
|
||||
settings.OPENEXCHANGERATES_KEY
|
||||
)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
currencies = AmiiboPrice.objects.all().distinct('currency')\
|
||||
.values_list('currency', flat=True)
|
||||
|
||||
rates = requests.get(self.rates_url).json()
|
||||
|
||||
result = {
|
||||
'base': rates['base'],
|
||||
'rates': {}
|
||||
}
|
||||
|
||||
for currency, rate in rates['rates'].iteritems():
|
||||
if currency in currencies:
|
||||
result['rates'][currency] = rate
|
||||
|
||||
handler = open(os.path.join(settings.MEDIA_ROOT, 'rates.json'), 'w')
|
||||
handler.write(json.dumps(result))
|
||||
handler.close()
|
||||
|
||||
print(result)
|
|
@ -78,7 +78,9 @@ TEMPLATES = [
|
|||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'amiibofindr.apps.amiibo.context_processors.collections',
|
||||
'amiibofindr.apps.amiibo.context_processors.currencies',
|
||||
'amiibofindr.apps.core.context_processors.debug',
|
||||
'amiibofindr.apps.core.context_processors.files',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -21,6 +21,8 @@ DATABASES = {
|
|||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = '/vagrant/media'
|
||||
|
||||
OPENEXCHANGERATES_KEY = 'aa703ed87a7749afab77b2966559c9df'
|
||||
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
(function() {
|
||||
var MoneyComponent = function() {
|
||||
this.DEBUG = DEBUG;
|
||||
this.currency = 'EUR';
|
||||
this.currencies = CURRENCIES;
|
||||
this.ratesSet = false;
|
||||
this.initialize();
|
||||
};
|
||||
|
||||
MoneyComponent.prototype.initialize = function() {
|
||||
// Load user currency
|
||||
this.refreshRates();
|
||||
this.handlers();
|
||||
var userCurrency = window.localStorage.getItem('currency');
|
||||
if (userCurrency && this.currencies.indexOf(userCurrency) !== -1) {
|
||||
this.currency = userCurrency;
|
||||
}
|
||||
this.setCurrency(this.currency);
|
||||
};
|
||||
|
||||
/*
|
||||
* Rates
|
||||
*/
|
||||
MoneyComponent.prototype.setRates = function(data) {
|
||||
if (!this.ratesSet) {
|
||||
if (typeof fx !== "undefined" && fx.rates) {
|
||||
fx.rates = data.rates;
|
||||
fx.base = data.base;
|
||||
}
|
||||
this.ratesSet = true;
|
||||
}
|
||||
};
|
||||
|
||||
MoneyComponent.prototype.refreshRates = function() {
|
||||
var self = this;
|
||||
$.getJSON(
|
||||
MEDIA_URL + '/rates.json',
|
||||
function(data) {
|
||||
data['time'] = new Date();
|
||||
window.localStorage.setItem('rates', JSON.stringify(data));
|
||||
self.setRates(data);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
MoneyComponent.prototype.setCurrency = function(currency) {
|
||||
var self = this;
|
||||
if (this.currencies.indexOf(currency) !== -1) {
|
||||
if (this.DEBUG) console.log('[money] set user currency: ' + currency)
|
||||
$('[data-currency-change]').removeClass('active');
|
||||
$('[data-currency-change="' + currency + '"]').addClass('active');
|
||||
window.localStorage.setItem('currency', currency);
|
||||
this.currency = currency;
|
||||
this.convertPrices();
|
||||
}
|
||||
};
|
||||
|
||||
MoneyComponent.prototype.convertPrices = function() {
|
||||
var self = this;
|
||||
if (!this.ratesSet) {
|
||||
if (this.DEBUG) console.log('[money] wait 300ms to convert prices...');
|
||||
setTimeout(function() {
|
||||
self.convertPrices()
|
||||
}, 300);
|
||||
return false;
|
||||
}
|
||||
[].forEach.call(document.querySelectorAll('[data-money]'), function(item) {
|
||||
var price = item.getAttribute('data-price');
|
||||
var currency = item.getAttribute('data-currency');
|
||||
if ((price && currency)) {
|
||||
if (currency != self.currency) {
|
||||
var conversion = fx(parseFloat(price)).from(currency).to(self.currency);
|
||||
if (self.DEBUG) console.log('[money] converting ' + price + ' from ' + currency + ' to ' + self.currency + ': ' + conversion);
|
||||
if (conversion) item.innerHTML = '<span class="price-converted">' + conversion.toFixed(2) + ' ' + self.currency + '</span>';
|
||||
} else {
|
||||
item.innerHTML = price + ' ' + currency;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
MoneyComponent.prototype.handlers = function() {
|
||||
var self = this;
|
||||
[].forEach.call(document.querySelectorAll('[data-currency-change]'), function(item) {
|
||||
var currency = item.getAttribute('data-currency-change');
|
||||
item.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
self.setCurrency(currency);
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
SimpleViews.register('money', MoneyComponent);
|
||||
})();
|
|
@ -0,0 +1,37 @@
|
|||
(function() {
|
||||
var SimpleViews = function() {
|
||||
this.views = {};
|
||||
var self = this;
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
self.onLoad();
|
||||
});
|
||||
};
|
||||
|
||||
SimpleViews.prototype.register = function(identifier, object) {
|
||||
if (identifier in this.views) {
|
||||
throw "Identifier '" + identifier + "' is already registered.";
|
||||
};
|
||||
this.views[identifier] = object;
|
||||
};
|
||||
|
||||
SimpleViews.prototype.loadView = function(identifier) {
|
||||
if (typeof(this.views[identifier]) === 'function') {
|
||||
console.log('[SimpleViews] loaded view: ' + identifier);
|
||||
this.views[identifier] = new this.views[identifier](window);
|
||||
} else {
|
||||
console.error('Identifier ' + identifier + ' not registered or already loaded.');
|
||||
}
|
||||
};
|
||||
|
||||
SimpleViews.prototype.onLoad = function() {
|
||||
var body = document.querySelector('body');
|
||||
var views = body.getAttribute('data-views').split(',');
|
||||
var self = this;
|
||||
[].forEach.call(views, function(view) {
|
||||
self.loadView(view);
|
||||
})
|
||||
};
|
||||
|
||||
window.SimpleViews = new SimpleViews();
|
||||
})(window);
|
|
@ -1,2 +1,11 @@
|
|||
// Semantic-UI
|
||||
@import "../semantic/semantic.css";
|
||||
|
||||
|
||||
.price-converted {
|
||||
font-style: italic;
|
||||
|
||||
&:before {
|
||||
content: '~';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<title>{% block page_title %}AmiiboFindr{% endblock %}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body data-views="{% block js_views %}{% endblock %}">
|
||||
<div class="ui page grid">
|
||||
<br />
|
||||
<div class="sixteen wide column">
|
||||
|
@ -21,25 +21,30 @@
|
|||
{% trans "Collections" %}
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<a class="item" href="#">{% trans "All" %}</a> {% for col in collections %}
|
||||
<a class="item" href="{{ col.get_absolute_url }}">{{ col.name }}</a> {% endfor %}
|
||||
<a class="item" href="#">{% trans "All" %}</a>
|
||||
{% for col in COLLECTIONS %}
|
||||
<a class="item" href="{{ col.get_absolute_url }}">{{ col.name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right menu"></div>
|
||||
</div>
|
||||
<div class="ui breadcrumb">
|
||||
{% block breadcrumb %}
|
||||
<a class="section" href="{% url 'amiibo:collection' 'all' %}">Home</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="ui breadcrumb">
|
||||
{% block breadcrumb %}
|
||||
<a class="section" href="{% url 'amiibo:collection' 'all' %}">Home</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% block main_content %}{% endblock %}
|
||||
<div class="ui page grid right aligned">
|
||||
<div class="sixteen wide column">
|
||||
<div class="ui page grid">
|
||||
<hr >
|
||||
<div class="eight wide column">
|
||||
<small>{% trans "CHANGE CURRENCY" %} {% for currency in CURRENCIES %}<a href="#" data-currency-change="{{ currency }}">{{ currency }}</a> {% endfor %}</small>
|
||||
</div>
|
||||
<div class="eight wide column right aligned">
|
||||
<div class="">
|
||||
AmiiboFindr © 2015 | <a href="https://twitter.com/amiibofindr" target="_blank"><i class="ui icon twitter"></i>Twitter</a>
|
||||
AmiiboFindr © 2015 | <a href="https://twitter.com/amiibofindr" target="_blank"><i class="ui icon twitter"></i>Twitter</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -53,6 +58,11 @@
|
|||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
var DEBUG = {{ DEBUG|yesno:"true,false" }};
|
||||
var MEDIA_URL = '{{ MEDIA_URL }}';
|
||||
var CURRENCIES = ['{{ CURRENCIES|join:"', '" }}'];
|
||||
</script>
|
||||
<script type="text/javascript" src={% static "dist/app.js" %}></script>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
{% block page_title %}{% blocktrans with collection=selected_collection.name amiibo=amiibo.name %}{{ amiibo }} amiibo from {{ collection }} in {% endblocktrans %}{{ block.super }}{% endblock %}
|
||||
|
||||
{% block js_views %}money{% endblock %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
|
@ -55,14 +56,14 @@
|
|||
<tbody>
|
||||
{% for relation in amiibo.shops_set.all %}
|
||||
<tr>
|
||||
{% with price=relation.last_price.price stock=relation.last_price.stock %}
|
||||
{% with price=relation.last_price.price stock=relation.last_price.stock currency=relation.last_price.currency %}
|
||||
<td><a href="{{ relation.get_url }}" target="_blank"><i class="{% if relation.shop.flag_code == 'uk' %}gb{% else %}{{ relation.shop.flag_code }}{% endif %} flag"></i> {{ relation.shop.name }}</a></td>
|
||||
<td class="center aligned {{ stock|yesno:'positive,negative' }}" {% if not price %}colspan="2"{% endif %}>
|
||||
<i class="icon {{ stock|yesno:'checkmark,close' }}"></i>
|
||||
{{ stock|yesno|capfirst }}
|
||||
</td>
|
||||
{% if price %}
|
||||
<td class="center aligned">
|
||||
<td class="center aligned" data-price="{{ price }}" data-currency="{{ currency }}" data-money>
|
||||
{{ price }} {{ relation.last_price.currency }}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"semantic-ui": "~1.12.3",
|
||||
"jquery": "~2.1.4"
|
||||
"jquery": "~2.1.4",
|
||||
"money": "~0.1.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@ var gulp = require('gulp'),
|
|||
gulp.task('scripts', function() {
|
||||
return gulp.src([
|
||||
'bower_components/jquery/dist/jquery.js',
|
||||
'bower_components/money/money.js',
|
||||
'amiibofindr/static/semantic/semantic.js',
|
||||
'amiibofindr/static/app/global.js'
|
||||
'amiibofindr/static/app/simpleViews.js',
|
||||
'amiibofindr/static/app/global.js',
|
||||
'amiibofindr/static/app/money.js'
|
||||
])
|
||||
.pipe(concat('app.js'))
|
||||
.pipe(gulp.dest('amiibofindr/static/dist'));
|
||||
|
|
Loading…
Reference in New Issue