diff --git a/backend/core/settings.py b/backend/core/settings.py index 97c840d..77f47bc 100644 --- a/backend/core/settings.py +++ b/backend/core/settings.py @@ -131,7 +131,7 @@ ROOT_URLCONF = 'core.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [BASE_DIR / "templates"], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -226,6 +226,7 @@ UNFOLD = { "SITE_HEADER": os.getenv("SITE_HEADER"), "SITE_URL": DOMAIN, "SITE_SYMBOL": "shield_person", + "DASHBOARD_CALLBACK": "core.views.dashboard_callback", "SITE_FAVICONS": [ { "rel": "icon", diff --git a/backend/core/views.py b/backend/core/views.py new file mode 100644 index 0000000..ca70765 --- /dev/null +++ b/backend/core/views.py @@ -0,0 +1,190 @@ +import json +import random +from functools import lru_cache + +from django.contrib.humanize.templatetags.humanize import intcomma +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ +from django.views.generic import RedirectView, TemplateView +from unfold.views import UnfoldModelAdminViewMixin + +class HomeView(RedirectView): + pattern_name = "admin:index" + + + + +def dashboard_callback(request, context): + + context.update(random_data()) + return context + + +@lru_cache +def random_data(): + WEEKDAYS = [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun", + ] + + positive = [[1, random.randrange(8, 28)] for i in range(1, 28)] + negative = [[-1, -random.randrange(8, 28)] for i in range(1, 28)] + average = [r[1] - random.randint(3, 5) for r in positive] + performance_positive = [[1, random.randrange(8, 28)] for i in range(1, 28)] + performance_negative = [[-1, -random.randrange(8, 28)] for i in range(1, 28)] + + response = { + "navigation": [ + {"title": _("Dashboard"), "link": "/", "active": True}, + {"title": _("Products"), "link": "/admin/product/productmodel/"}, + {"title": _("Orders"), "link": "/admin/order/ordermodel/"}, + ], + "kpi": [ + { + "title": "Product A Performance", + "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "footer": mark_safe( + f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% progress from last week' + ), + "chart": json.dumps( + { + "labels": [WEEKDAYS[day % 7] for day in range(1, 28)], + "datasets": [{"data": average, "borderColor": "#9333ea"}], + } + ), + }, + { + "title": "Product B Performance", + "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "footer": mark_safe( + f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% progress from last week' + ), + }, + { + "title": "Product C Performance", + "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "footer": mark_safe( + f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% progress from last week' + ), + }, + ], + "progress": [ + { + "title": "🦆 Social marketing e-book", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🦍 Freelancing tasks", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🐋 Development coaching", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🦑 Product consulting", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🐨 Other income", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🐶 Course sales", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🐻❄️ Ads revenue", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🦩 Customer Retention Rate", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🦊 Marketing ROI", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + { + "title": "🦁 Affiliate partnerships", + "description": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}", + "value": random.randint(10, 90), + }, + ], + "chart": json.dumps( + { + "labels": [WEEKDAYS[day % 7] for day in range(1, 28)], + "datasets": [ + { + "label": "Example 1", + "type": "line", + "data": average, + "borderColor": "var(--color-primary-500)", + }, + { + "label": "Example 2", + "data": positive, + "backgroundColor": "var(--color-primary-700)", + }, + { + "label": "Example 3", + "data": negative, + "backgroundColor": "var(--color-primary-300)", + }, + ], + } + ), + "performance": [ + { + "title": _("Last week revenue"), + "metric": "$1,234.56", + "footer": mark_safe( + '+3.14% progress from last week' + ), + "chart": json.dumps( + { + "labels": [WEEKDAYS[day % 7] for day in range(1, 28)], + "datasets": [ + { + "data": performance_positive, + "borderColor": "var(--color-primary-700)", + } + ], + } + ), + }, + { + "title": _("Last week expenses"), + "metric": "$1,234.56", + "footer": mark_safe( + '+3.14% progress from last week' + ), + "chart": json.dumps( + { + "labels": [WEEKDAYS[day % 7] for day in range(1, 28)], + "datasets": [ + { + "data": performance_negative, + "borderColor": "var(--color-primary-300)", + }, + ], + } + ), + }, + ], + } + return response diff --git a/backend/templates/admin/base_site.html b/backend/templates/admin/base_site.html new file mode 100644 index 0000000..f349bd7 --- /dev/null +++ b/backend/templates/admin/base_site.html @@ -0,0 +1,13 @@ +{% extends "admin/base.html" %} + +{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} + +{% block branding %} +
+ {% trans "Did you decide to start using Unfold in your application but you need help with integration? Feel free to get in touch for consulting, priority support on specific tickets or development services." %} +
+