Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit b20319c

Browse files
committed
added dashboard app
1 parent 1c0727e commit b20319c

13 files changed

Lines changed: 437 additions & 2 deletions

File tree

apps/dashboard/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
default_app_config = 'apps.dashboard.apps.DashboardConfig'

apps/dashboard/apps.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.apps import AppConfig
5+
from django.utils.translation import ugettext_lazy as _
6+
7+
8+
class DashboardConfig(AppConfig):
9+
name = 'apps.dashboard'
10+
verbose_name = _('App Dashboard')

apps/dashboard/urls.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.urls import path
5+
6+
from apps.dashboard.views.index import DashboardIndexView
7+
8+
app_name = 'apps.dashboard'
9+
10+
urlpatterns = [
11+
path('', DashboardIndexView.as_view(), name='dashboard_index'),
12+
]

apps/dashboard/views/__init__.py

Whitespace-only changes.

apps/dashboard/views/index.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""
2+
Dashboard Index Views
3+
to show all statistics.
4+
"""
5+
# -*- coding: utf-8 -*-
6+
from __future__ import unicode_literals
7+
8+
from django.utils import timezone
9+
from django.utils.translation import ugettext_lazy as _
10+
from django.views.generic import TemplateView
11+
12+
from core.utils.mixins import SuperUserLoginRequiredMixin
13+
14+
from apps.accounts.models.user import User
15+
from apps.product.models.product import Product
16+
from apps.blog.models.addons import Visitor
17+
from apps.blog.models.post import Post
18+
from apps.blog.models.tag import Tag
19+
20+
21+
class DashboardIndexView(SuperUserLoginRequiredMixin, TemplateView):
22+
template_name = 'apps/dashboard/index.html'
23+
now = timezone.now()
24+
25+
def get_total_tags(self, period: str, month: int = None) -> int:
26+
"""
27+
function to get the total tags per-month / year.
28+
:param `period` is string period (choices: "year", "month")
29+
:param `month` is optional integer month if it period as "month".
30+
:return int total of tags.
31+
"""
32+
if period == 'year':
33+
return Tag.objects.filter(
34+
created_at__year=self.now.year
35+
).count()
36+
elif period == 'month':
37+
return Tag.objects.filter(
38+
created_at__year=self.now.year,
39+
created_at__month=month
40+
).count()
41+
return 0
42+
43+
def get_total_users(self, period: str, month: int = None) -> int:
44+
"""
45+
function to get the total users per-month / year.
46+
:param `period` is string period (choices: "year", "month")
47+
:param `month` is optional integer month if it period as "month".
48+
:return int total of users
49+
"""
50+
if period == 'year':
51+
return User.objects.filter(
52+
date_joined__year=self.now.year
53+
).count()
54+
elif period == 'month':
55+
return User.objects.filter(
56+
date_joined__year=self.now.year,
57+
date_joined__month=month
58+
).count()
59+
return 0
60+
61+
def get_total_posts(self, period: str, month: int = None) -> int:
62+
"""
63+
function to get the total posts per-month / year.
64+
:param `period` is string period (choices: "year", "month")
65+
:param `month` is optional integer month if it period as "month".
66+
:return int total of posts.
67+
"""
68+
if period == 'year':
69+
return Post.objects.filter(
70+
created_at__year=self.now.year
71+
).count()
72+
elif period == 'month':
73+
return Post.objects.filter(
74+
created_at__year=self.now.year,
75+
created_at__month=month
76+
).count()
77+
return 0
78+
79+
def get_total_visitors(self, period: str, month: int = None) -> int:
80+
"""
81+
function to get the total visitors per-month / year.
82+
:param `period` is string period (choices: "year", "month")
83+
:param `month` is optional integer month if it period as "month".
84+
:return int total of visitors.
85+
"""
86+
if period == 'year':
87+
return Visitor.objects.filter(
88+
created_at__year=self.now.year
89+
).count()
90+
elif period == 'month':
91+
return Visitor.objects.filter(
92+
created_at__year=self.now.year,
93+
created_at__month=month
94+
).count()
95+
return 0
96+
97+
def get_data_visitors_per_months(self) -> list:
98+
"""
99+
function to get the calculate the total data
100+
of visitors for each month.
101+
:return list dict of data per month.
102+
"""
103+
data_per_months = []
104+
for month in range(1, 12):
105+
total = self.get_total_visitors(period='month', month=month)
106+
data_per_months.append(total)
107+
return data_per_months
108+
109+
def get_data_per_months(self) -> list:
110+
"""
111+
function to get the calculate the total data
112+
includes (user, product) for each month.
113+
:return list dict of data per month.
114+
"""
115+
data_per_months = []
116+
for month in range(1, 12):
117+
data_per_months.append({
118+
'tag': self.get_total_tags(period='month', month=month),
119+
'post': self.get_total_posts(period='month', month=month),
120+
'user': self.get_total_users(period='month', month=month)
121+
})
122+
return data_per_months
123+
124+
def get_context_data(self, **kwargs):
125+
context_data = super().get_context_data(**kwargs)
126+
context_data['total_tags'] = Tag.objects.all().count()
127+
context_data['total_tags_this_year'] = self.get_total_tags(period='year')
128+
context_data['total_users'] = User.objects.all().count()
129+
context_data['total_users_this_year'] = self.get_total_users(period='year')
130+
context_data['total_posts'] = Post.objects.all().count()
131+
context_data['total_posts_this_year'] = self.get_total_posts(period='year')
132+
context_data['total_visitors'] = Visitor.objects.all().count()
133+
context_data['total_visitors_this_year'] = self.get_total_visitors(period='year')
134+
context_data['data_visitors_per_months'] = self.get_data_visitors_per_months()
135+
context_data['data_per_months'] = self.get_data_per_months()
136+
return context_data

core/settings.py.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ INSTALLED_APPS = [
8989
'apps.blog',
9090
'apps.product',
9191
'apps.api',
92+
'apps.dashboard',
9293
]
9394

9495

core/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
path('', include('apps.blog.urls')),
3131
path('', include('apps.product.urls')),
3232
path('api/', include('apps.api.urls')),
33+
path('dash/', include('apps.dashboard.urls')),
3334
]
3435

3536
if settings.DEBUG:

core/utils/mixins.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.contrib.auth.mixins import LoginRequiredMixin
5+
6+
7+
class SuperUserLoginRequiredMixin(LoginRequiredMixin):
8+
9+
def dispatch(self, request, *args, **kwargs):
10+
if request.user.is_authenticated:
11+
if request.user.is_superuser:
12+
return super().dispatch(request, *args, **kwargs)
13+
return self.handle_no_permission()

templates/apps/accounts/user/profile.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,14 @@ <h5 class="text-bold">+ {{ user|get_total_posts|numberize }}</h5>
274274
<span class="badge badge-light">{{ tag_data.total }}</span>
275275
</div>
276276
</div>
277+
{% empty %}
278+
<div class="col-md-12">
279+
<ul class="list-group list-group-flush list-group-posts">
280+
<li class="list-group-item">
281+
<span>{% blocktrans with user=user %}{{ user }} dosen't have tags!{% endblocktrans %}</span>
282+
</li>
283+
</ul>
284+
</div>
277285
{% endfor %}
278286
</div>
279287
</div>

templates/apps/blog/page/detail.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@
2323
{% endblock %}
2424

2525
{% block css %}
26+
<link href="{% static 'plugins/css/ace.min.css' %}" rel="stylesheet" media="all">
2627
<link href="{% static 'martor/css/martor.bootstrap.min.css' %}" rel="stylesheet" media="all">
2728
<style>div.martor-preview {border: 1px dashed #ddd}div.martor-preview hr{background-image: linear-gradient(to right,silver 50%,rgba(255,255,255,0) 40%); background-position: top; background-size: 3px 1px; background-repeat: repeat-x; height: 1px; border-top: 0; border-bottom: 0;}</style>
2829
{% endblock %}
2930

3031

3132
{% block content %}
3233
<div class="container p-3">
33-
<h5 class="mt-5 pt-4"><a class="no-underline" href="">{{ page_title }}</a></h5>
34+
<h5><a class="no-underline" href="">{{ page_title }}</a></h5>
3435
<div class="mt-4 row row-content">
3536
<div class="col-md-8">
3637
<div class="martor-preview">

0 commit comments

Comments
 (0)