Improve service interface
This commit is contained in:
parent
654b628fc9
commit
fc2919d642
1
Pipfile
1
Pipfile
@ -22,6 +22,7 @@ gunicorn = "*"
|
|||||||
psycopg2 = "*"
|
psycopg2 = "*"
|
||||||
redis = "*"
|
redis = "*"
|
||||||
django-redis-cache = "*"
|
django-redis-cache = "*"
|
||||||
|
pycountry = "*"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.6"
|
python_version = "3.6"
|
||||||
|
21
Pipfile.lock
generated
21
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "ed79d7965e276156d03c4710bf0d6b35750f9f87d37750d50838b53aeeaaa815"
|
"sha256": "c7c9248fad70f86dda59b61f823f0992276c6cb9ee7ead05ae5719077c0c0c1f"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -90,11 +90,11 @@
|
|||||||
},
|
},
|
||||||
"django-redis-cache": {
|
"django-redis-cache": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:5c581743de5994e6b15abfd5b3dbcb8bf00e42d97658c96b7218bcb6a63f863b",
|
"sha256:06d4e48545243883f88dc9263dda6c8a0012cb7d0cee2d8758d8917eca92cece",
|
||||||
"sha256:bc0eaf20d275708e0437cbea28f9965e1922c15291f6206edbef3966c029836b"
|
"sha256:b19ee6654cc2f2c89078c99255e07e19dc2dba8792351d76ba7ea899d465fbb0"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.1.0"
|
"version": "==2.1.1"
|
||||||
},
|
},
|
||||||
"emoji-country-flag": {
|
"emoji-country-flag": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@ -174,6 +174,13 @@
|
|||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.8.5"
|
"version": "==2.8.5"
|
||||||
},
|
},
|
||||||
|
"pycountry": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3c57aa40adcf293d59bebaffbe60d8c39976fba78d846a018dc0c2ec9c6cb3cb"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==19.8.18"
|
||||||
|
},
|
||||||
"python3-openid": {
|
"python3-openid": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0086da6b6ef3161cfe50fb1ee5cceaf2cda1700019fda03c2c5c440ca6abe4fa",
|
"sha256:0086da6b6ef3161cfe50fb1ee5cceaf2cda1700019fda03c2c5c440ca6abe4fa",
|
||||||
@ -258,10 +265,10 @@
|
|||||||
},
|
},
|
||||||
"urllib3": {
|
"urllib3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
|
"sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
|
||||||
"sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
|
"sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
|
||||||
],
|
],
|
||||||
"version": "==1.25.8"
|
"version": "==1.25.9"
|
||||||
},
|
},
|
||||||
"user-agents": {
|
"user-agents": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -63,7 +63,7 @@ class Service(models.Model):
|
|||||||
Hit = apps.get_model("analytics", "Hit")
|
Hit = apps.get_model("analytics", "Hit")
|
||||||
|
|
||||||
currently_online = Session.objects.filter(
|
currently_online = Session.objects.filter(
|
||||||
service=self, start_time__gt=timezone.now() - timezone.timedelta(seconds=10)
|
service=self, last_seen__gt=timezone.now() - timezone.timedelta(seconds=10)
|
||||||
).count()
|
).count()
|
||||||
|
|
||||||
sessions = Session.objects.filter(
|
sessions = Session.objects.filter(
|
||||||
@ -92,6 +92,12 @@ class Service(models.Model):
|
|||||||
.order_by("-count")
|
.order_by("-count")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
countries = (
|
||||||
|
sessions.values("country")
|
||||||
|
.annotate(count=models.Count("country"))
|
||||||
|
.order_by("-count")
|
||||||
|
)
|
||||||
|
|
||||||
operating_systems = (
|
operating_systems = (
|
||||||
sessions.values("os").annotate(count=models.Count("os")).order_by("-count")
|
sessions.values("os").annotate(count=models.Count("os")).order_by("-count")
|
||||||
)
|
)
|
||||||
@ -165,6 +171,7 @@ class Service(models.Model):
|
|||||||
"avg_hits_per_session": avg_hits_per_session,
|
"avg_hits_per_session": avg_hits_per_session,
|
||||||
"locations": locations,
|
"locations": locations,
|
||||||
"referrers": referrers,
|
"referrers": referrers,
|
||||||
|
"countries": countries,
|
||||||
"operating_systems": operating_systems,
|
"operating_systems": operating_systems,
|
||||||
"browsers": browsers,
|
"browsers": browsers,
|
||||||
"devices": devices,
|
"devices": devices,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<a class="card ~neutral !low service mb-6 p-0" href="{% url 'dashboard:service' object.uuid %}">
|
<a class="card ~neutral !low service mb-6 p-0" href="{% url 'dashboard:service' object.uuid %}">
|
||||||
{% with stats=object.stats %}
|
{% with stats=object.stats %}
|
||||||
<div class="p-4 md:flex justify-between">
|
<div class="p-4 md:flex justify-between">
|
||||||
<div class="md:w-4/12 flex items-center mb-4 md:mb-0">
|
<div class="flex items-center mb-4 md:mb-0">
|
||||||
<h3 class="heading text-xl md:text-2xl mr-2 mb-1 text-purple-600">
|
<h3 class="heading text-xl md:text-2xl mr-2 mb-1 text-purple-600">
|
||||||
{{object.name}}
|
{{object.name}}
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -5,13 +5,5 @@
|
|||||||
<span class="chip ~positive !high">
|
<span class="chip ~positive !high">
|
||||||
{{stats.currently_online|intcomma}} online
|
{{stats.currently_online|intcomma}} online
|
||||||
</span>
|
</span>
|
||||||
{% elif stats.online == True %}
|
|
||||||
<span class="chip ~positive !high">
|
|
||||||
Online
|
|
||||||
</span>
|
|
||||||
{% elif stats.online == False %}
|
|
||||||
<span class="chip ~critical !high">
|
|
||||||
Offline
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
@ -105,6 +105,24 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card ~neutral !low limited-height py-2">
|
||||||
|
<table class="table">
|
||||||
|
<thead class="text-sm">
|
||||||
|
<tr>
|
||||||
|
<th>Country</th>
|
||||||
|
<th class="rf">Sessions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for country in stats.countries %}
|
||||||
|
<tr>
|
||||||
|
<td>{{country.country|flag_emoji}} {{country.country|country_name}}</td>
|
||||||
|
<td class="rf">{{country.count|intcomma}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div class="card ~neutral !low limited-height py-2">
|
<div class="card ~neutral !low limited-height py-2">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead class="text-sm">
|
<thead class="text-sm">
|
||||||
@ -141,24 +159,6 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="card ~neutral !low limited-height py-2">
|
|
||||||
<table class="table">
|
|
||||||
<thead class="text-sm">
|
|
||||||
<tr>
|
|
||||||
<th>Device</th>
|
|
||||||
<th class="rf">Sessions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for device in stats.devices %}
|
|
||||||
<tr>
|
|
||||||
<td>{{device.device|default:"Unknown"}}</td>
|
|
||||||
<td class="rf">{{device.count|intcomma}}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="card ~neutral !low limited-height py-2">
|
<div class="card ~neutral !low limited-height py-2">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead class="text-sm">
|
<thead class="text-sm">
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Country</p>
|
<p>Country</p>
|
||||||
<p class="label">{{session.country|flag_emoji}} {{session.country|default:"Unknown"}}</p>
|
<p class="label">{{session.country|flag_emoji}} {{session.country|country_name}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Location</p>
|
<p>Location</p>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
import pycountry
|
||||||
import flag
|
import flag
|
||||||
from django import template
|
from django import template
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@ -30,6 +30,12 @@ def flag_emoji(isocode):
|
|||||||
except:
|
except:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def country_name(isocode):
|
||||||
|
try:
|
||||||
|
return pycountry.countries.get(alpha_2=isocode).name
|
||||||
|
except:
|
||||||
|
return "Unknown"
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def startswith(text, starts):
|
def startswith(text, starts):
|
||||||
|
Loading…
Reference in New Issue
Block a user