diff --git a/config/settings/base.py b/config/settings/base.py index 154eb26..3dd3f1f 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -205,7 +205,6 @@ THUMBNAIL_ALIASES = { LANGUAGES = [ ('en', _('English')), - ('fa', _('Persian')), ('ru', _('Russia')), ] LOCALE_PATHS = [ @@ -323,6 +322,22 @@ LOGIN_REDIRECT_URL = reverse_lazy("home") ###################################################################### from utils.admin import admin_url_generator , is_dovoodi_panel , is_main_panel +# --- ENHANCED DYNAMIC BADGE FUNCTION --- +def get_pending_certificates_badge(request): + try: + from apps.certificate.models import Certificate + qs = Certificate.objects.filter(status='pending') + + # If user is a professor (not staff/admin), only show their pending certificates + if request.user.is_authenticated and not request.user.is_staff and not getattr(request.user, 'is_superuser', False): + qs = qs.filter(course__professor=request.user) + + count = qs.count() + return str(count) if count > 0 else None + except Exception as e: + print(f"Badge Error: {e}") # Fails safely in terminal if DB isn't migrated yet + return None + UNFOLD = { # "SITE_TITLE": _("Imam Jawad Admin"), # "SITE_HEADER": _("Imam Jawad Admin"), @@ -341,6 +356,7 @@ UNFOLD = { # ], "SITE_SYMBOL": "settings", + "ALLOW_UNICODE_SLUGS": True, "SHOW_HISTORY": True, "SHOW_LANGUAGES": True, "ENVIRONMENT": "utils.environment_callback", @@ -359,7 +375,7 @@ UNFOLD = { # - FormulaAdminSite: پالت سبز برای امام جواد # - DovoodiAdminSite: پالت آبی-تیره برای داوودی (مطابق فرانت) "STYLES": [ - # lambda request: static("css/styles.css"), + lambda request: static("css/styles.css"), ], "SCRIPTS": [ # lambda request: static("js/chart.min.js"), @@ -470,19 +486,19 @@ UNFOLD = { "title": _("Course Lessons"), "icon": "menu_book", "link": lambda request: admin_url_generator(request, "course_courselesson_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_courselesson_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_courselesson_changelist")), }, { "title": _("Course Attachments"), "icon": "attach_file", "link": lambda request: admin_url_generator(request, "course_courseattachment_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_courseattachment_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_courseattachment_changelist")), }, { "title": _("Course Glossary"), "icon": "book", "link": lambda request: admin_url_generator(request, "course_courseglossary_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_courseglossary_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_courseglossary_changelist")), }, ], @@ -496,22 +512,22 @@ UNFOLD = { ], "items": [ { - "title": _("Course Onlines"), + "title": _("Live Sessions"), "icon": "video_call", "link": lambda request: admin_url_generator(request, "course_courselivesession_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_courselivesession_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_courselivesession_changelist")), }, { "title": _("Session Users"), "icon": "groups", "link": lambda request: admin_url_generator(request, "course_livesessionuser_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_livesessionuser_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_livesessionuser_changelist")), }, { "title": _("Session Recordings"), "icon": "play_circle", "link": lambda request: admin_url_generator(request, "course_livesessionrecording_changelist"), - "active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_livesessionrecording_changelist"))), + "active": lambda request: request.path.startswith(admin_url_generator(request, "course_livesessionrecording_changelist")), }, ], }, @@ -533,25 +549,55 @@ UNFOLD = { }, ], }, + { + "page": "quizzes", + "models": [ + "quiz.quiz", + "quiz.quizparticipant" + ], + "items": [ + { + "title": _("Quizzes"), + "icon": "quiz", + "link": lambda request: admin_url_generator(request, "quiz_quiz_changelist"), + "active": lambda request: request.path.startswith(admin_url_generator(request, "quiz_quiz_changelist")), + }, + { + "title": _("Quiz Participants"), + "icon": "group", + "link": lambda request: admin_url_generator(request, "quiz_quizparticipant_changelist"), + "active": lambda request: request.path.startswith(admin_url_generator(request, "quiz_quizparticipant_changelist")), + }, + ], + }, ], "SIDEBAR": { "show_search": True, "show_all_applications": True, "navigation": [ + # --- 1. OVERVIEW --- { "title": _(""), - "separator": True, - "collapsible": True, + "separator": False, "items": [ { "title": _("Dashboard"), "icon": "dashboard", "link": lambda request: admin_url_generator(request, "index"), }, + { + "title": _("Calender"), + "icon": "calendar_today", + "link": lambda request: admin_url_generator(request, "dobodbi_calendar_calendaroccasions_changelist"), + "permission": is_dovoodi_panel, + }, ], }, + + # --- 2. USER MANAGEMENT --- { "title": _(""), + "separator": True, "items": [ { "title": _("Authentication"), @@ -559,172 +605,117 @@ UNFOLD = { "link": lambda request: admin_url_generator(request, "auth_group_changelist"), "permission": lambda request: request.user.is_staff, }, - ], - }, - { - "title": _(""), - "items": [ { - "title": _("Users"), - "icon": "person", + "title": _("All Users"), + "icon": "people", "link": lambda request: admin_url_generator(request, "account_user_changelist"), "permission": lambda request: request.user.is_staff, }, - ], - }, - { - "title": _(""), - "items": [ - { + { "title": _("Students"), - "icon": "school", + "icon": "face", "link": lambda request: admin_url_generator(request, "account_studentuser_changelist"), "permission": is_main_panel, - }, - - ] - }, - { - "title": _(""), - "items": [ - { + }, + { "title": _("Professors"), - "icon": "person_book", + "icon": "history_edu", "link": lambda request: admin_url_generator(request, "account_professoruser_changelist"), "permission": is_main_panel, - }, - - ] - }, - { - "title": _(""), - "items": [ - { - "title": _("Calender"), - "icon": "calendar_today", - "link": lambda request: admin_url_generator(request, "dobodbi_calendar_calendaroccasions_changelist"), - "permission": is_dovoodi_panel, }, ], }, + # --- 3. ACADEMICS (Collapsible) --- { "title": _("Courses"), "collapsible": True, "separator": True, - "permission":is_main_panel, + "permission": is_main_panel, "items": [ { "title": _("Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "course_coursecategory_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, }, { "title": _("Courses"), "icon": "school", "link": lambda request: admin_url_generator(request, "course_course_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Lessons"), - "icon": "menu_book", - "link": lambda request: admin_url_generator(request, "course_lesson_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Attachments"), - "icon": "attach_file", - "link": lambda request: admin_url_generator(request, "course_attachment_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Glossary"), - "icon": "book", - "link": lambda request: admin_url_generator(request, "course_glossary_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, }, { "title": _("Live Sessions"), - "icon": "video_call", + "icon": "video_camera_front", "link": lambda request: admin_url_generator(request, "course_courselivesession_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Session Users"), - "icon": "groups", - "link": lambda request: admin_url_generator(request, "course_livesessionuser_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Session Recordings"), - "icon": "play_circle", - "link": lambda request: admin_url_generator(request, "course_livesessionrecording_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, }, { "title": _("Certificates"), "icon": "workspace_premium", "link": lambda request: admin_url_generator(request, "certificate_certificate_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, + "badge": "utils.admin.get_pending_certificates_badge", }, - ] + ] }, + + # --- 4. ASSESSMENTS --- { - "title": _("Quizzes"), - "collapsible": True, + "title": _(""), "separator": True, - "permission":is_main_panel, + "permission": is_main_panel, "items": [ { "title": _("Quizzes"), "icon": "quiz", "link": lambda request: admin_url_generator(request, "quiz_quiz_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, }, - { - "title": _("Quiz Participants"), - "icon": "group", - "link": lambda request: admin_url_generator(request, "quiz_quizparticipant_changelist"), - "permission":is_main_panel, - }, - ] - }, - { - "title": _("Transactions"), - "collapsible": True, - "separator": True, - "items": [ { "title": _("Transactions"), "icon": "payments", "link": lambda request: admin_url_generator(request, "transaction_transactionparticipant_changelist"), - "permission":is_main_panel, + "permission": is_main_panel, + }, + { + "title": _("Chat Rooms"), + "icon": "forum", + "link": lambda request: admin_url_generator(request, "chat_roommessage_changelist"), + "permission": is_main_panel, + }, + { + "title": _("Blogs"), + "icon": "article", + "link": lambda request: admin_url_generator(request, "blog_blog_changelist"), + "permission": is_main_panel, }, ] }, + # --- DOVOODI SECTIONS --- { "title": _("Libraries"), "collapsible": True, "separator": True, - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, "items": [ { "title": _("Books"), "icon": "menu_book", "link": lambda request: admin_url_generator(request, "library_book_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "library_category_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Collections"), "icon": "view_module", "link": lambda request: admin_url_generator(request, "library_pinnedbookcollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, ] }, @@ -732,53 +723,31 @@ UNFOLD = { "title": _("Videos"), "collapsible": True, "separator": True, - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, "items": [ { "title": _("Videos"), "icon": "live_tv", "link": lambda request: admin_url_generator(request, "video_video_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "video_videocategory_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Collections"), "icon": "view_module", "link": lambda request: admin_url_generator(request, "video_pinnedvideocollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Playlists"), "icon": "playlist_play", "link": lambda request: admin_url_generator(request, "video_videoplaylist_changelist"), - "permission":is_dovoodi_panel, - # "active": lambda request: "video/videoplaylist" in request.path, - }, - - ] - }, - { - "title": _("Blog"), - "collapsible": True, - "separator": True, - "permission":is_main_panel, - "items": [ - { - "title": _("Comments"), - "icon": "comment", - "link": lambda request: admin_url_generator(request, "api_comment_changelist"), - "permission":is_main_panel, - }, - { - "title": _("Blogs"), - "icon": "article", - "link": lambda request: admin_url_generator(request, "blog_blog_changelist"), - "permission":is_main_panel, + "permission": is_dovoodi_panel, }, ] }, @@ -786,37 +755,37 @@ UNFOLD = { "title": _("Articles"), "collapsible": True, "separator": True, - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, "items": [ { "title": _("Articles"), "icon": "article", "link": lambda request: admin_url_generator(request, "article_article_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "article_articlecategory_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Pinned Collections"), "icon": "collections_bookmark", "link": lambda request: admin_url_generator(request, "article_pinnedarticlecollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Regular Collections"), "icon": "view_module", "link": lambda request: admin_url_generator(request, "article_middlearticlecollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Article Contents"), "icon": "text_snippet", "link": lambda request: admin_url_generator(request, "article_articlecontent_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, ] }, @@ -824,181 +793,129 @@ UNFOLD = { "title": _("Podcasts"), "collapsible": True, "separator": True, - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, "items": [ { "title": _("Podcasts"), "icon": "headset", "link": lambda request: admin_url_generator(request, "podcast_podcast_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "podcast_podcastcategory_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Pinned Collections"), "icon": "collections_bookmark", "link": lambda request: admin_url_generator(request, "podcast_pinnedpodcastcollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Regular Collections"), "icon": "view_module", "link": lambda request: admin_url_generator(request, "podcast_middlepodcastcollection_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Playlists"), "icon": "playlist_play", "link": lambda request: admin_url_generator(request, "podcast_podcastplaylist_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("User Playlists"), "icon": "person_add", "link": lambda request: admin_url_generator(request, "podcast_userplaylist_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, ] }, - { - "title": _("Chats"), - "collapsible": True, - "separator": True, - "permission":is_main_panel, - "items": [ - { - "title": _("Chat Rooms"), - "icon": "forum", - "link": lambda request: admin_url_generator(request, "chat_roommessage_changelist"), - "permission":is_main_panel, - }, - # { - # "title": _("Chat Messages"), - # "icon": "chat", - # "link": lambda request: admin_url_generator(request, "apps_chat_chatmessage_changelist"), - # }, - # { - # "title": _("Read Status"), - # "icon": "mark_chat_read", - # "link": lambda request: admin_url_generator(request, "apps_chat_messagereadstatus_changelist"), - # }, - ] - }, { "title": _("Hadis"), "collapsible": True, "separator": True, - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, "items": [ { "title": _("Hadis Sects"), "icon": "account_tree", "link": lambda request: admin_url_generator(request, "hadis_hadissect_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis Categories"), "icon": "category", "link": lambda request: admin_url_generator(request, "hadis_hadiscategory_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis"), "icon": "format_quote", "link": lambda request: admin_url_generator(request, "hadis_hadis_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis References"), "icon": "link", "link": lambda request: admin_url_generator(request, "hadis_hadisreference_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis Tags"), "icon": "label", "link": lambda request: admin_url_generator(request, "hadis_hadistag_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis Status"), "icon": "flag", "link": lambda request: admin_url_generator(request, "hadis_hadisstatus_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Transmitters"), "icon": "person", "link": lambda request: admin_url_generator(request, "hadis_transmitters_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, { "title": _("Hadis Transmitters"), "icon": "group", "link": lambda request: admin_url_generator(request, "hadis_hadistransmitter_changelist"), - "permission":is_dovoodi_panel, + "permission": is_dovoodi_panel, }, ] }, + + # --- 7. SYSTEM SETTINGS --- { - "title": _(""), + "title": _("System Settings"), + "separator": True, "items": [ { "title": _("App Versions"), "icon": "system_update", "link": lambda request: admin_url_generator(request, "api_appversion_changelist"), }, - ], - }, - { - "title": "", - "items": [ { "title": _("Global Preferences"), - "icon": "settings", + "icon": "tune", "link": lambda request: admin_url_generator(request, "dynamic_preferences_globalpreferencemodel_changelist"), }, - # You can add more preference sections here ], }, - # "STYLES": [ - # lambda request: static("css/styles.css"), - # ], - # "SCRIPTS": [ - # lambda request: static("js/scripts.js"), - # ], ], - }, + } } UNFOLD_STUDIO_DEFAULT_FRAGMENT = "color-schemes" UNFOLD_STUDIO_PERMISSION = lambda request: request.user.is_authenticated PLAUSIBLE_DOMAIN = env("PLAUSIBLE_DOMAIN") -# uncomment it just to check if redis caches and signals works fine locally - -# CACHES = { -# 'default': { -# "BACKEND": "django_redis.cache.RedisCache", -# "LOCATION": "redis://127.0.0.1:6379/1", -# "OPTIONS": { -# "CLIENT_CLASS": "django_redis.client.DefaultClient", -# } -# }, -# 'memory': { -# 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', -# 'LOCATION': 'unique-snowflake', -# 'TIMEOUT': 5000, -# }, -# } - sentry_sdk.init( dsn="https://31aaeeb3a42f9a8c1b26272a0cb8ad3e@o4507991743725568.ingest.us.sentry.io/4511127356768256", - # Add data like request headers and IP for users, - # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info send_default_pii=True, ) \ No newline at end of file diff --git a/templates/admin/index.html b/templates/admin/index.html index c2f6d1a..5a05999 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -1,24 +1,46 @@ -{% extends 'admin/base.html' %} - +{% extends "admin/base_site.html" %} {% load i18n unfold %} {% block breadcrumbs %}{% endblock %} {% block title %} - {% trans 'Dashboard' %} | {{ site_title|default:_('Django site admin') }} -{% endblock %} - -{% block extrahead %} - {% if plausible_domain %} - - {% endif %} +{% trans 'Dashboard' %} | {{ site_title|default:_('Django site admin') }} {% endblock %} {% block branding %} - {% include "unfold/helpers/site_branding.html" %} +{% include "unfold/helpers/site_branding.html" %} {% endblock %} {% block content %} - {% include "unfold/helpers/messages.html" %} -{% endblock %} +{% include "unfold/helpers/messages.html" %} +
+ {% trans "No statistics available for this panel." %} +
+ {% endfor %} +