You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
924 lines
36 KiB
924 lines
36 KiB
"""
|
|
Django settings for backend project.
|
|
|
|
Generated by 'django-admin startproject' using Django 5.0.4.
|
|
|
|
For more information on this file, see
|
|
https://docs.djangoproject.com/en/5.0/topics/settings/
|
|
|
|
For the full list of settings and their values, see
|
|
https://docs.djangoproject.com/en/5.0/ref/settings/
|
|
"""
|
|
import os
|
|
from pathlib import Path
|
|
from django.templatetags.static import static
|
|
from django.urls import reverse_lazy
|
|
|
|
import environ
|
|
from django.utils.translation import gettext_lazy as _
|
|
import sentry_sdk
|
|
|
|
|
|
env = environ.Env(
|
|
# set casting, default value
|
|
# DEBUG=(bool, False)
|
|
)
|
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
|
|
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
|
|
|
|
ALLOWED_HOSTS = env('DJANGO_ALLOWED_HOSTS').split(',')
|
|
CSRF_TRUSTED_ORIGINS = env('DJANGO_TRUSTED_ORIGINS').split(',')
|
|
|
|
|
|
# Quick-start development settings - unsuitable for production
|
|
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
|
|
|
# SECURITY WARNING: keep the secret key used in production secret!
|
|
SECRET_KEY = 'django-insecure-7=3it+m^28^+0c1*9-*c*6g3ej63sz(97rq1^mp=!6e(mhmysh'
|
|
|
|
# SECURITY WARNING: don't run with debug turned on in production!
|
|
DEBUG = True
|
|
|
|
X_FRAME_OPTIONS = 'SAMEORIGIN'
|
|
|
|
LOCAL_APPS = [
|
|
'apps.account.apps.AccountConfig',
|
|
'apps.api.apps.ApiConfig',
|
|
'apps.course.apps.CourseConfig',
|
|
'apps.chat.apps.ChatConfig',
|
|
'apps.quiz.apps.QuizConfig',
|
|
'apps.transaction.apps.TransactionConfig',
|
|
'apps.certificate.apps.CertificateConfig',
|
|
'apps.hadis.apps.HadisConfig',
|
|
'apps.library.apps.LibraryConfig',
|
|
'apps.video.apps.VideoConfig',
|
|
'apps.podcast.apps.PodcastConfig',
|
|
'apps.bookmark.apps.BookmarkConfig',
|
|
'apps.article.apps.ArticleConfig',
|
|
'apps.dobodbi_calendar.apps.DobodbiCalendarConfig',
|
|
'apps.blog.apps.BlogConfig',
|
|
'apps.agent.apps.AgentConfig',
|
|
'dynamic_preferences',
|
|
'apps.geolocation_package',
|
|
|
|
]
|
|
|
|
THIRD_PARTY_APPS = [
|
|
'rest_framework',
|
|
'rest_framework.authtoken',
|
|
'drf_yasg',
|
|
'rosetta',
|
|
'easy_thumbnails',
|
|
'phonenumber_field',
|
|
'dj_language',
|
|
'dj_filer',
|
|
'ajaxdatatable',
|
|
'dj_category',
|
|
'corsheaders',
|
|
'django_filters',
|
|
|
|
]
|
|
INSTALLED_APPS = [
|
|
"unfold",
|
|
"unfold.contrib.filters",
|
|
"unfold.contrib.import_export",
|
|
"unfold.contrib.guardian",
|
|
"unfold.contrib.simple_history",
|
|
"unfold.contrib.forms",
|
|
"unfold.contrib.inlines",
|
|
"whitenoise.runserver_nostatic",
|
|
# 'limitless_dashboard.apps.DashboardConfig',
|
|
'django.contrib.admin',
|
|
'django.contrib.auth',
|
|
'django.contrib.contenttypes',
|
|
'django.contrib.sessions',
|
|
'django.contrib.messages',
|
|
'django.contrib.staticfiles',
|
|
'django.contrib.humanize', # Added for humanize template tags
|
|
*THIRD_PARTY_APPS,
|
|
*LOCAL_APPS,
|
|
|
|
]
|
|
AUTHENTICATION_BACKENDS = [
|
|
'django.contrib.auth.backends.ModelBackend', # این خط را نگه دارید تا احراز هویت پیشفرض کار کند
|
|
'apps.account.custom_user_login.CustomLoginBackend', # مسیر به کلاس سفارشی خود
|
|
]
|
|
|
|
REDIS_URL = env('REDIS_URL')
|
|
|
|
|
|
|
|
OTP_SERIVCE_KEY = "33213d78f1234e99b81f94eefda77e45"
|
|
|
|
RESEND_API_KEY = "re_JFFAfESy_JHmJTJLu5ToGTPhwrZx7trKd"
|
|
RESEND_FROM_EMAIL = "info@imamjavad.online"
|
|
|
|
|
|
PHONENUMBER_DEFAULT_REGION = "IR"
|
|
PHONENUMBER_DB_FORMAT = 'INTERNATIONAL'
|
|
PHONENUMBER_DEFAULT_FORMAT = 'INTERNATIONAL'
|
|
|
|
AUTH_USER_MODEL = "account.User"
|
|
MIDDLEWARE = [
|
|
'config.middleware.site_middleware.SiteMiddleware', # Must be first to route by domain
|
|
'django.middleware.security.SecurityMiddleware',
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
'corsheaders.middleware.CorsMiddleware',
|
|
'django.middleware.locale.LocaleMiddleware',
|
|
'django.middleware.common.CommonMiddleware',
|
|
'django.middleware.csrf.CsrfViewMiddleware',
|
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
# "django.contrib.auth.middleware.LoginRequiredMiddleware",
|
|
'django.contrib.messages.middleware.MessageMiddleware',
|
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
'config.language_code_middleware.language_middleware',
|
|
'config.enhanced_auth_middleware.enhanced_auth_middleware',
|
|
'apps.account.middleware.admin_access.AdminAccessMiddleware',
|
|
]
|
|
ROOT_URLCONF = 'config.urls'
|
|
|
|
TEMPLATES = [
|
|
{
|
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
'DIRS': [
|
|
BASE_DIR / 'templates',
|
|
],
|
|
'APP_DIRS': True,
|
|
'OPTIONS': {
|
|
'context_processors': [
|
|
'django.template.context_processors.debug',
|
|
'django.template.context_processors.request',
|
|
'django.contrib.auth.context_processors.auth',
|
|
'django.contrib.messages.context_processors.messages',
|
|
'django.template.context_processors.i18n',
|
|
"utils.admin.variables",
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
WSGI_APPLICATION = 'config.wsgi.application'
|
|
|
|
|
|
# django google recaptcha default keys
|
|
RECAPTCHA_PUBLIC_KEY = env('captcha_public_key')
|
|
RECAPTCHA_PRIVATE_KEY = env('captcha_private_key')
|
|
|
|
APPS_REORDER = {
|
|
'auth': {
|
|
'icon': 'icon-shield-check',
|
|
'name': 'Authentication'
|
|
},
|
|
'account': {
|
|
# 'icon': 'icon-',
|
|
'name': 'account'
|
|
}
|
|
}
|
|
# Database
|
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
|
|
|
DATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.postgresql',
|
|
'NAME': env('POSTGRES_DB'),
|
|
'USER': env('POSTGRES_USER'),
|
|
'PASSWORD': env('POSTGRES_PASSWORD'),
|
|
'HOST': env('POSTGRES_HOST'),
|
|
'PORT': env('POSTGRES_PORT'),
|
|
'ATOMIC_REQUESTS': True,
|
|
},
|
|
}
|
|
|
|
|
|
CORS_ALLOW_ALL_ORIGINS = True
|
|
|
|
THUMBNAIL_ALIASES = {
|
|
'': {
|
|
'icon': {'size': (50, 50), 'crop': True},
|
|
'large': {'size': (1200, 620), 'crop': False},
|
|
'medium': {'size': (545, 545), 'crop': False},
|
|
'small': {'size': (150, 150), 'crop': False},
|
|
},
|
|
}
|
|
|
|
|
|
|
|
LANGUAGES = [
|
|
('en', _('English')),
|
|
('ru', _('Russia')),
|
|
]
|
|
LOCALE_PATHS = [
|
|
os.path.join(BASE_DIR, 'locale'),
|
|
]
|
|
|
|
CELERY_BROKER_URL = env("REDIS_URL")
|
|
CELERY_RESULT_BACKEND = env("REDIS_URL")
|
|
CELERY_ACCEPT_CONTENT = ['application/json']
|
|
CELERY_TIMEZONE = 'Asia/Tehran'
|
|
CELERY_BROKER_TRANSPORT = 'redis'
|
|
CELERY_ACCEPT_CONTENT = ['json']
|
|
CELERY_TASK_SERIALIZER = 'json'
|
|
CELERY_RESULT_SERIALIZER = 'json'
|
|
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
|
|
|
|
# Password validation
|
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
|
|
|
|
|
|
AUTH_PASSWORD_VALIDATORS = [
|
|
{
|
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
'OPTIONS': {
|
|
'min_length': 6,
|
|
}
|
|
},
|
|
]
|
|
|
|
|
|
REST_FRAMEWORK = {
|
|
'DEFAULT_PAGINATION_CLASS': 'utils.pagination.StandardResultsSetPagination',
|
|
'PAGE_SIZE': 16,
|
|
# 'DEFAULT_AUTHENTICATION_CLASSES': [
|
|
# 'apps.account.auth_back.TokenAuthentication2',
|
|
# ],
|
|
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
|
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
|
'rest_framework.authentication.TokenAuthentication',
|
|
# 'rest_framework.authentication.SessionAuthentication',
|
|
],
|
|
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
|
|
'EXCEPTION_HANDLER': 'utils.exceptions.exception_handler',
|
|
|
|
|
|
}
|
|
# Internationalization
|
|
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
|
|
|
LANGUAGE_CODE = 'en'
|
|
|
|
TIME_ZONE = 'Asia/Tehran'
|
|
|
|
USE_I18N = True
|
|
|
|
USE_L10N = True
|
|
|
|
USE_TZ = False
|
|
|
|
STATIC_URL = '/static/'
|
|
MEDIA_URL = '/media/'
|
|
|
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
|
|
# *********************************************************
|
|
STATIC_ROOT = BASE_DIR/'staticfiles'
|
|
MEDIA_ROOT = BASE_DIR/'media'
|
|
# os.path.join(BASE_DIR, 'static', 'media')
|
|
|
|
# FILER_ADMIN_ICON_SIZES = ('32', '48')
|
|
|
|
FILER_ENABLE_LOGGING = True
|
|
FILER_DEBUG = True
|
|
ADMIN_TITLE = 'Imam Javad App'
|
|
ADMIN_INDEX_TITLE = 'Imam Javad Administration'
|
|
SITE_DOMAIN = "https://imamjavad.newhorizonco.uk"
|
|
DOVODI_DOMAIN = "https://dovodi.newhorizonco.uk"
|
|
ONLINE_CLASS_FRONTEND_DOMAIN = env('ONLINE_CLASS_FRONTEND_DOMAIN', default=SITE_DOMAIN)
|
|
ONLINE_CLASS_TOKEN_TTL = env.int('ONLINE_CLASS_TOKEN_TTL', default=3000)
|
|
PLUGNMEET_SERVER_URL ='https://meet.newhorizonco.uk'
|
|
PLUGNMEET_API_KEY ='habibmeet_api_key_2024'
|
|
PLUGNMEET_API_SECRET ='habibmeet_secret_zumyyYWqv7KR2kUqvYdq4z4sXg7XTBD2ljT6_2024'
|
|
PLUGNMEET_TIMEOUT = env.float('PLUGNMEET_TIMEOUT', default=10.0)
|
|
|
|
|
|
# Static files (CSS, JavaScript, Images)
|
|
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
|
|
|
|
|
# Default primary key field type
|
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
|
|
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
FILE_UPLOAD_HANDLERS = [
|
|
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
|
|
]
|
|
|
|
|
|
|
|
######################################################################
|
|
# Sessions
|
|
######################################################################
|
|
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
|
|
LOGIN_URL = "admin:login"
|
|
LOGIN_REDIRECT_URL = reverse_lazy("home")
|
|
# STORAGES = {
|
|
# "default": {
|
|
# "BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
# },
|
|
# "staticfiles": {
|
|
# "BACKEND": "whitenoise.storage.CompressedStaticFilesStorage",
|
|
# },
|
|
# }
|
|
######################################################################
|
|
# Unfold
|
|
######################################################################
|
|
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"),
|
|
# "SITE_SUBHEADER": _("Imam Jawad Online School"),
|
|
# "SITE_DROPDOWN": [
|
|
# {
|
|
# "icon": "diamond",
|
|
# "title": _("Imam Javad Site"),
|
|
# "link": "https://habibapp.com",
|
|
# },
|
|
# {
|
|
# "title": _("Dovoodi Site"),
|
|
# "link": "https://dovodi.newhorizonco.uk/",
|
|
# "icon": "diamond",
|
|
# },
|
|
|
|
# ],
|
|
"SITE_SYMBOL": "settings",
|
|
"ALLOW_UNICODE_SLUGS": True,
|
|
"SHOW_HISTORY": True,
|
|
"SHOW_LANGUAGES": True,
|
|
"ENVIRONMENT": "utils.environment_callback",
|
|
"DASHBOARD_CALLBACK": "utils.admin.dashboard_callback",
|
|
"SITE_ICON": {
|
|
"light": lambda request: static("images/dovoodi_logo.svg") if is_dovoodi_panel(request) else static("images/logo1.svg"),
|
|
"dark": lambda request: static("images/dovoodi_logo.svg") if is_dovoodi_panel(request) else static("images/logo1.svg"),
|
|
},
|
|
"SITE_SYMBOL": "speed",
|
|
"SHOW_BACK_BUTTON": True, # show/hide "Back" button on changeform in header, default: False
|
|
"THEME": "light",
|
|
"LOGIN": {
|
|
"image": lambda request: static("images/dovoodi_login.png") if is_dovoodi_panel(request) else static("images/image1.jpg"),
|
|
},
|
|
# ✅ COLORS حذف شد - هر AdminSite رنگهای خودش را در utils/admin.py تعریف میکند
|
|
# - FormulaAdminSite: پالت سبز برای امام جواد
|
|
# - DovoodiAdminSite: پالت آبی-تیره برای داوودی (مطابق فرانت)
|
|
"STYLES": [
|
|
lambda request: static("css/styles.css"),
|
|
],
|
|
"SCRIPTS": [
|
|
# lambda request: static("js/chart.min.js"),
|
|
],
|
|
"TABS": [
|
|
{
|
|
"page": "video",
|
|
"models": ["video.videocollection", "video.pinnedvideocollection", 'video.middlevideocollection',],
|
|
"items": [
|
|
{
|
|
"title": _("Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "video_pinnedvideocollection_changelist"),
|
|
"active": lambda request: "video/pinnedvideocollection" in request.path and "library/middlevideocollection" not in request.path,
|
|
},
|
|
{
|
|
"title": _("Middle Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "video_middlevideocollection_changelist"),
|
|
"active": lambda request: "video/middlevideocollection" in request.path,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "library",
|
|
"models": ["library.bookcollection", "library.pinnedbookcollection", 'library.middlebookcollection'],
|
|
"items": [
|
|
{
|
|
"title": _("Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "library_pinnedbookcollection_changelist"),
|
|
"active": lambda request: "library/pinnedbookcollection" in request.path and "library/middlebookcollection" not in request.path,
|
|
},
|
|
{
|
|
"title": _("Middle Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "library_middlebookcollection_changelist"),
|
|
"active": lambda request: "library/middlebookcollection" in request.path,
|
|
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "article",
|
|
"models": ["article.articlecollection", "article.pinnedarticlecollection", "article.middlearticlecollection"],
|
|
"items": [
|
|
{
|
|
"title": _("Pinned Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "article_pinnedarticlecollection_changelist"),
|
|
"active": lambda request: "article/pinnedarticlecollection" in request.path and "article/middlearticlecollection" not in request.path,
|
|
},
|
|
{
|
|
"title": _("Regular Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "article_middlearticlecollection_changelist"),
|
|
"active": lambda request: "article/middlearticlecollection" in request.path,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "accounts",
|
|
"models": ["account.user", 'auth.group'],
|
|
"items": [
|
|
{
|
|
"title": _("Users"),
|
|
"icon": "sports_motorsports",
|
|
"link": lambda request: admin_url_generator(request, "account_user_changelist"),
|
|
# "active": lambda request: request.path
|
|
# == lambda request: admin_url_generator(request, "account_user_changelist")
|
|
# and "email__isnull" not in request.GET,
|
|
},
|
|
{
|
|
"title": _("Guest Users"),
|
|
"icon": "sports_motorsports",
|
|
"link": lambda request: f"{admin_url_generator(request, 'account_user_changelist')}?email__isnull=true",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "authentication",
|
|
"models": ["auth.group", "auth.permission"],
|
|
"permission": lambda request: request.user.is_staff,
|
|
"items": [
|
|
{
|
|
"title": _("Groups"),
|
|
"icon": "shield",
|
|
"link": lambda request: admin_url_generator(request, "auth_group_changelist"),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "courses",
|
|
"models": [
|
|
"course.course",
|
|
"course.courselesson",
|
|
"course.courseglossary",
|
|
"course.courseattachment",
|
|
],
|
|
"items": [
|
|
{
|
|
"title": _("Courses"),
|
|
"icon": "school",
|
|
"link": lambda request: admin_url_generator(request, "course_course_changelist"),
|
|
"active": lambda request: request.path.startswith(str(lambda request: admin_url_generator(request, "course_course_changelist"))),
|
|
},
|
|
{
|
|
"title": _("Course Lessons"),
|
|
"icon": "menu_book",
|
|
"link": 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(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(admin_url_generator(request, "course_courseglossary_changelist")),
|
|
},
|
|
|
|
],
|
|
},
|
|
{
|
|
"page": "course_online",
|
|
"models": [
|
|
"course.courselivesession",
|
|
"course.livesessionuser",
|
|
"course.livesessionrecording",
|
|
],
|
|
"items": [
|
|
{
|
|
"title": _("Live Sessions"),
|
|
"icon": "video_call",
|
|
"link": 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(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(admin_url_generator(request, "course_livesessionrecording_changelist")),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"page": "podcast",
|
|
"models": ["podcast.podcastcollection", "podcast.pinnedpodcastcollection", "podcast.middlepodcastcollection"],
|
|
"items": [
|
|
{
|
|
"title": _("Pinned Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "podcast_pinnedpodcastcollection_changelist"),
|
|
"active": lambda request: "podcast/pinnedpodcastcollection" in request.path and "podcast/middlepodcastcollection" not in request.path,
|
|
},
|
|
{
|
|
"title": _("Regular Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "podcast_middlepodcastcollection_changelist"),
|
|
"active": lambda request: "podcast/middlepodcastcollection" in request.path,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"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": 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"),
|
|
"icon": "shield",
|
|
"link": lambda request: admin_url_generator(request, "auth_group_changelist"),
|
|
"permission": lambda request: request.user.is_staff,
|
|
},
|
|
{
|
|
"title": _("All Users"),
|
|
"icon": "people",
|
|
"link": lambda request: admin_url_generator(request, "account_user_changelist"),
|
|
"permission": lambda request: request.user.is_staff,
|
|
},
|
|
{
|
|
"title": _("Students"),
|
|
"icon": "face",
|
|
"link": lambda request: admin_url_generator(request, "account_studentuser_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
{
|
|
"title": _("Professors"),
|
|
"icon": "history_edu",
|
|
"link": lambda request: admin_url_generator(request, "account_professoruser_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
],
|
|
},
|
|
# --- 3. ACADEMICS (Collapsible) ---
|
|
{
|
|
"title": _("Courses"),
|
|
"collapsible": True,
|
|
"separator": True,
|
|
"permission": is_main_panel,
|
|
"items": [
|
|
{
|
|
"title": _("Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "course_coursecategory_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
{
|
|
"title": _("Courses"),
|
|
"icon": "school",
|
|
"link": lambda request: admin_url_generator(request, "course_course_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
{
|
|
"title": _("Live Sessions"),
|
|
"icon": "video_camera_front",
|
|
"link": lambda request: admin_url_generator(request, "course_courselivesession_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
{
|
|
"title": _("Certificates"),
|
|
"icon": "workspace_premium",
|
|
"link": lambda request: admin_url_generator(request, "certificate_certificate_changelist"),
|
|
"permission": is_main_panel,
|
|
"badge": "utils.admin.get_pending_certificates_badge",
|
|
},
|
|
]
|
|
},
|
|
|
|
# --- 4. ASSESSMENTS ---
|
|
{
|
|
"title": _(""),
|
|
"separator": True,
|
|
"permission": is_main_panel,
|
|
"items": [
|
|
{
|
|
"title": _("Quizzes"),
|
|
"icon": "quiz",
|
|
"link": lambda request: admin_url_generator(request, "quiz_quiz_changelist"),
|
|
"permission": is_main_panel,
|
|
},
|
|
{
|
|
"title": _("Transactions"),
|
|
"icon": "payments",
|
|
"link": lambda request: admin_url_generator(request, "transaction_transactionparticipant_changelist"),
|
|
"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,
|
|
"items": [
|
|
{
|
|
"title": _("Books"),
|
|
"icon": "menu_book",
|
|
"link": lambda request: admin_url_generator(request, "library_book_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "library_category_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "library_pinnedbookcollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"title": _("Videos"),
|
|
"collapsible": True,
|
|
"separator": True,
|
|
"permission": is_dovoodi_panel,
|
|
"items": [
|
|
{
|
|
"title": _("Videos"),
|
|
"icon": "live_tv",
|
|
"link": lambda request: admin_url_generator(request, "video_video_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "video_videocategory_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "video_pinnedvideocollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Playlists"),
|
|
"icon": "playlist_play",
|
|
"link": lambda request: admin_url_generator(request, "video_videoplaylist_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"title": _("Articles"),
|
|
"collapsible": True,
|
|
"separator": True,
|
|
"permission": is_dovoodi_panel,
|
|
"items": [
|
|
{
|
|
"title": _("Articles"),
|
|
"icon": "article",
|
|
"link": lambda request: admin_url_generator(request, "article_article_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "article_articlecategory_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Pinned Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "article_pinnedarticlecollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Regular Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "article_middlearticlecollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Article Contents"),
|
|
"icon": "text_snippet",
|
|
"link": lambda request: admin_url_generator(request, "article_articlecontent_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"title": _("Podcasts"),
|
|
"collapsible": True,
|
|
"separator": True,
|
|
"permission": is_dovoodi_panel,
|
|
"items": [
|
|
{
|
|
"title": _("Podcasts"),
|
|
"icon": "headset",
|
|
"link": lambda request: admin_url_generator(request, "podcast_podcast_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "podcast_podcastcategory_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Pinned Collections"),
|
|
"icon": "collections_bookmark",
|
|
"link": lambda request: admin_url_generator(request, "podcast_pinnedpodcastcollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Regular Collections"),
|
|
"icon": "view_module",
|
|
"link": lambda request: admin_url_generator(request, "podcast_middlepodcastcollection_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Playlists"),
|
|
"icon": "playlist_play",
|
|
"link": lambda request: admin_url_generator(request, "podcast_podcastplaylist_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("User Playlists"),
|
|
"icon": "person_add",
|
|
"link": lambda request: admin_url_generator(request, "podcast_userplaylist_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"title": _("Hadis"),
|
|
"collapsible": True,
|
|
"separator": True,
|
|
"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,
|
|
},
|
|
{
|
|
"title": _("Hadis Categories"),
|
|
"icon": "category",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadiscategory_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Hadis"),
|
|
"icon": "format_quote",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadis_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Hadis References"),
|
|
"icon": "link",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadisreference_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Hadis Tags"),
|
|
"icon": "label",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadistag_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Hadis Status"),
|
|
"icon": "flag",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadisstatus_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Transmitters"),
|
|
"icon": "person",
|
|
"link": lambda request: admin_url_generator(request, "hadis_transmitters_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
{
|
|
"title": _("Hadis Transmitters"),
|
|
"icon": "group",
|
|
"link": lambda request: admin_url_generator(request, "hadis_hadistransmitter_changelist"),
|
|
"permission": is_dovoodi_panel,
|
|
},
|
|
]
|
|
},
|
|
|
|
# --- 7. SYSTEM SETTINGS ---
|
|
{
|
|
"title": _("System Settings"),
|
|
"separator": True,
|
|
"items": [
|
|
{
|
|
"title": _("App Versions"),
|
|
"icon": "system_update",
|
|
"link": lambda request: admin_url_generator(request, "api_appversion_changelist"),
|
|
},
|
|
{
|
|
"title": _("Global Preferences"),
|
|
"icon": "tune",
|
|
"link": lambda request: admin_url_generator(request, "dynamic_preferences_globalpreferencemodel_changelist"),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
}
|
|
UNFOLD_STUDIO_DEFAULT_FRAGMENT = "color-schemes"
|
|
UNFOLD_STUDIO_PERMISSION = lambda request: request.user.is_authenticated
|
|
|
|
PLAUSIBLE_DOMAIN = env("PLAUSIBLE_DOMAIN")
|
|
|
|
sentry_sdk.init(
|
|
dsn="https://31aaeeb3a42f9a8c1b26272a0cb8ad3e@o4507991743725568.ingest.us.sentry.io/4511127356768256",
|
|
send_default_pii=True,
|
|
)
|