Autosave: 20260204-171755

This commit is contained in:
Flatlogic Bot 2026-02-04 17:17:56 +00:00
parent f4cb2d0af8
commit 0da3beb95c
12 changed files with 343 additions and 50 deletions

View File

@ -43,6 +43,8 @@ SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = "None"
CSRF_COOKIE_SAMESITE = "None"
LANGUAGE_COOKIE_SAMESITE = "None"
LANGUAGE_COOKIE_SECURE = True
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/

View File

@ -5,9 +5,10 @@ from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('i18n/', include('django.conf.urls.i18n')),
path('', include('core.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -101,3 +101,12 @@ class PackageAdmin(ActionsModelAdmin):
list_editable = ('is_active',)
filter_horizontal = ('subjects',)
search_fields = ('name_en', 'name_ar')
class Media:
js = ('js/admin_package.js',)
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
if obj and obj.classroom:
form.base_fields['subjects'].queryset = Subject.objects.filter(classroom=obj.classroom)
return form

View File

@ -1,14 +1,18 @@
{% load i18n static %}
{% get_current_language as LANGUAGE_CODE %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<html lang="{{ LANGUAGE_CODE }}" dir="{% if LANGUAGE_CODE == 'ar' %}rtl{% else %}ltr{% endif %}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}منصة التعليم الإلكتروني{% endblock %}</title>
<title>{% block title %}{% if LANGUAGE_CODE == 'ar' %}منصة التعليم الإلكتروني{% else %}EduPlatform{% endif %}{% endblock %}</title>
<!-- Bootstrap 5 CDN (RTL) -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
<!-- Bootstrap 5 CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap{% if LANGUAGE_CODE == 'ar' %}.rtl{% endif %}.min.css" rel="stylesheet">
<!-- FontAwesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@ -91,6 +95,11 @@
background: radial-gradient(circle, rgba(45, 49, 250, 0.1) 0%, transparent 70%);
z-index: 0;
}
html[dir="ltr"] .hero-section::before {
right: auto;
left: 0;
}
.footer {
padding: 3rem 0;
@ -122,35 +131,62 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="#">الدورات</a>
<a class="nav-link" href="#">{% if LANGUAGE_CODE == 'ar' %}الدورات{% else %}Courses{% endif %}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">المعلمون</a>
<a class="nav-link" href="#">{% if LANGUAGE_CODE == 'ar' %}المعلمون{% else %}Teachers{% endif %}</a>
</li>
{% if user.is_staff %}
<li class="nav-item">
<a class="nav-link" href="/admin/">المسؤول</a>
<a class="nav-link" href="/admin/">{% if LANGUAGE_CODE == 'ar' %}المسؤول{% else %}Admin{% endif %}</a>
</li>
{% endif %}
</ul>
<div class="d-flex align-items-center">
<!-- Language Switcher -->
<div class="dropdown mx-3">
<button class="btn btn-link nav-link p-0 text-dark d-flex align-items-center gap-2 dropdown-toggle text-decoration-none" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-globe fa-lg text-primary"></i>
<span class="small fw-bold">{{ LANGUAGE_CODE|upper }}</span>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0" aria-labelledby="languageDropdown" style="border-radius: 12px;">
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<li>
<form action="{% url 'set_language' %}" method="post" class="d-block">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}">
<input name="language" type="hidden" value="{{ language.code }}">
<button type="submit" class="dropdown-item py-2 d-flex justify-content-between align-items-center {% if language.code == LANGUAGE_CODE %}bg-light text-primary fw-bold{% endif %}">
<span>{{ language.name_local }}</span>
{% if language.code == LANGUAGE_CODE %}
<i class="fas fa-check small"></i>
{% endif %}
</button>
</form>
</li>
{% endfor %}
</ul>
</div>
{% if user.is_authenticated %}
<div class="dropdown ms-2">
<button class="btn btn-link text-decoration-none dropdown-toggle text-dark d-flex align-items-center" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<span class="fw-semibold">{{ user.username }}</span>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0" aria-labelledby="userDropdown" style="border-radius: 12px;">
<li><a class="dropdown-item py-2" href="{% url 'profile' %}">الملف الشخصي</a></li>
<li><a class="dropdown-item py-2" href="{% url 'profile' %}">{% if LANGUAGE_CODE == 'ar' %}الملف الشخصي{% else %}Profile{% endif %}</a></li>
{% if user.is_staff %}
<li><a class="dropdown-item py-2" href="/admin/">لوحة تحكم المسؤول</a></li>
<li><a class="dropdown-item py-2" href="/admin/">{% if LANGUAGE_CODE == 'ar' %}لوحة تحكم المسؤول{% else %}Dashboard{% endif %}</a></li>
{% endif %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item py-2 text-danger" href="{% url 'logout' %}">تسجيل الخروج</a></li>
<li><a class="dropdown-item py-2 text-danger" href="{% url 'logout' %}">{% if LANGUAGE_CODE == 'ar' %}تسجيل الخروج{% else %}Logout{% endif %}</a></li>
</ul>
</div>
{% else %}
<a href="{% url 'register_student' %}" class="btn btn-outline-primary me-2">تسجيل</a>
<a href="{% url 'login' %}" class="btn btn-primary">دخول</a>
<a href="{% url 'register_student' %}" class="btn btn-outline-primary me-2">{% if LANGUAGE_CODE == 'ar' %}تسجيل{% else %}Register{% endif %}</a>
<a href="{% url 'login' %}" class="btn btn-primary">{% if LANGUAGE_CODE == 'ar' %}دخول{% else %}Login{% endif %}</a>
{% endif %}
</div>
</div>
@ -161,7 +197,7 @@
<footer class="footer mt-5">
<div class="container text-center">
<p>&copy; 2026 EduPlatform. جميع الحقوق محفوظة.</p>
<p>&copy; 2026 EduPlatform. {% if LANGUAGE_CODE == 'ar' %}جميع الحقوق محفوظة.{% else %}All rights reserved.{% endif %}</p>
</div>
</footer>

View File

@ -1,7 +1,9 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}الرئيسية | EduPlatform{% endblock %}
{% block title %}
{% if LANGUAGE_CODE == 'ar' %}الرئيسية | منصة التعليم الإلكتروني{% else %}Home | EduPlatform{% endif %}
{% endblock %}
{% block content %}
<section class="hero-section">
@ -9,14 +11,26 @@
<div class="row align-items-center">
<div class="col-lg-6">
<h1 class="display-4 fw-bold mb-4">
تعلم من أفضل المعلمين في أي وقت وأي مكان
{% if LANGUAGE_CODE == 'ar' %}
تعلم من أفضل المعلمين في أي وقت وأي مكان
{% else %}
Learn from the best teachers anytime, anywhere
{% endif %}
</h1>
<p class="lead mb-5 text-muted">
منصة تعليمية متكاملة تدعم الطلاب والمعلمين مع دروس حية ومصادر تعليمية متميزة.
{% if LANGUAGE_CODE == 'ar' %}
منصة تعليمية متكاملة تدعم الطلاب والمعلمين مع دروس حية ومصادر تعليمية متميزة.
{% else %}
A comprehensive educational platform supporting students and teachers with live lessons and premium resources.
{% endif %}
</p>
<div class="d-flex gap-3">
<a href="#levels-section" class="btn btn-primary btn-lg px-5">ابدأ الآن</a>
<a href="#" class="btn btn-outline-secondary btn-lg px-5">اعرف المزيد</a>
<a href="#levels-section" class="btn btn-primary btn-lg px-5">
{% if LANGUAGE_CODE == 'ar' %}ابدأ الآن{% else %}Start Now{% endif %}
</a>
<a href="#" class="btn btn-outline-secondary btn-lg px-5">
{% if LANGUAGE_CODE == 'ar' %}اعرف المزيد{% else %}Learn More{% endif %}
</a>
</div>
</div>
<div class="col-lg-6 d-none d-lg-block">
@ -24,8 +38,12 @@
<div style="width: 400px; height: 400px; background: var(--primary-color); border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; opacity: 0.1; position: absolute; top: -50px; left: 50px;"></div>
<div style="width: 300px; height: 300px; background: var(--secondary-color); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; opacity: 0.1; position: absolute; bottom: -50px; right: 50px;"></div>
<div class="glass-card text-center position-relative z-1">
<h3 class="fw-bold mb-3">مستعد للبدء؟</h3>
<p>انضم لآلاف الطلاب اليوم.</p>
<h3 class="fw-bold mb-3">
{% if LANGUAGE_CODE == 'ar' %}مستعد للبدء؟{% else %}Ready to Start?{% endif %}
</h3>
<p>
{% if LANGUAGE_CODE == 'ar' %}انضم لآلاف الطلاب اليوم.{% else %}Join thousands of students today.{% endif %}
</p>
<div class="avatar-group d-flex justify-content-center mt-4">
<div style="width: 40px; height: 40px; border-radius: 50%; background: #ccc; border: 2px solid #fff; margin-left: -10px;"></div>
<div style="width: 40px; height: 40px; border-radius: 50%; background: #ddd; border: 2px solid #fff; margin-left: -10px;"></div>
@ -41,8 +59,12 @@
<section id="levels-section" class="subjects-section py-5">
<div class="container">
<div class="text-center mb-5">
<h2 class="fw-bold">برامجنا التعليمية</h2>
<p class="text-muted">استكشف المواد المخصصة لكل مرحلة دراسية.</p>
<h2 class="fw-bold">
{% if LANGUAGE_CODE == 'ar' %}برامجنا التعليمية{% else %}Our Educational Programs{% endif %}
</h2>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}استكشف المواد المخصصة لكل مرحلة دراسية.{% else %}Explore subjects tailored for each educational level.{% endif %}
</p>
</div>
{% for level in levels %}
@ -52,7 +74,7 @@
{{ forloop.counter }}
</div>
<h3 class="fw-bold mb-0">
{{ level.name_ar }}
{% if LANGUAGE_CODE == 'ar' %}{{ level.name_ar }}{% else %}{{ level.name_en|default:level.name_ar }}{% endif %}
</h3>
<hr class="flex-grow-1 ms-4 d-none d-md-block opacity-10">
</div>
@ -63,21 +85,27 @@
<div class="glass-card h-100 p-0 overflow-hidden shadow-sm">
<div style="height: 180px; background: {% cycle '#E3F2FD' '#F3E5F5' '#E8F5E9' %}; display: flex; align-items: center; justify-content: center;">
{% if subject.image %}
<img src="{{ subject.image.url }}" class="img-fluid" alt="{{ subject.name_en }}">
<img src="{{ subject.image.url }}" class="img-fluid" alt="{% if LANGUAGE_CODE == 'ar' %}{{ subject.name_ar }}{% else %}{{ subject.name_en }}{% endif %}">
{% else %}
<span class="display-2" style="opacity: 0.2;">📚</span>
{% endif %}
</div>
<div class="p-4">
<h4 class="fw-bold mb-3">
{{ subject.name_ar }}
{% if LANGUAGE_CODE == 'ar' %}{{ subject.name_ar }}{% else %}{{ subject.name_en|default:subject.name_ar }}{% endif %}
</h4>
<p class="text-muted small mb-4">
{{ subject.description_ar|truncatewords:15 }}
{% if LANGUAGE_CODE == 'ar' %}
{{ subject.description_ar|truncatewords:15 }}
{% else %}
{{ subject.description_en|default:subject.description_ar|truncatewords:15 }}
{% endif %}
</p>
<div class="d-flex justify-content-between align-items-center">
<span class="h5 fw-bold mb-0 text-primary">${{ subject.price }}</span>
<a href="{% url 'subject_detail' subject.pk %}" class="btn btn-primary btn-sm">اشتراك</a>
<a href="{% url 'subject_detail' subject.pk %}" class="btn btn-primary btn-sm">
{% if LANGUAGE_CODE == 'ar' %}اشتراك{% else %}Subscribe{% endif %}
</a>
</div>
</div>
</div>
@ -85,7 +113,7 @@
{% empty %}
<div class="col-12">
<div class="alert alert-light border-0 text-center py-4">
لا توجد مواد متاحة لهذا المستوى بعد.
{% if LANGUAGE_CODE == 'ar' %}لا توجد مواد متاحة لهذا المستوى بعد.{% else %}No subjects available for this level yet.{% endif %}
</div>
</div>
{% endfor %}
@ -99,8 +127,12 @@
<section id="teachers-section" class="py-5 bg-light">
<div class="container">
<div class="text-center mb-5">
<h2 class="fw-bold">تعرف على معلمينا</h2>
<p class="text-muted">تعلم من نخبة من المعلمين.</p>
<h2 class="fw-bold">
{% if LANGUAGE_CODE == 'ar' %}تعرف على معلمينا{% else %}Meet Our Teachers{% endif %}
</h2>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}تعلم من نخبة من المعلمين.{% else %}Learn from elite educators.{% endif %}
</p>
</div>
<div class="row g-4 justify-content-center">
@ -122,13 +154,15 @@
<p class="text-primary small fw-bold mb-3">{{ teacher.specialization|default:"معلم" }}</p>
<p class="text-muted small mb-4">
{{ teacher.bio|default:"لا توجد نبذة."|truncatewords:20 }}
{{ teacher.bio|default:"No bio available."|truncatewords:20 }}
</p>
</div>
</div>
{% empty %}
<div class="col-12 text-center">
<p class="text-muted">لا يوجد معلمين حالياً.</p>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}لا يوجد معلمين حالياً.{% else %}No teachers available at the moment.{% endif %}
</p>
</div>
{% endfor %}
</div>
@ -141,22 +175,34 @@
<div class="col-md-4">
<div class="p-4">
<div class="mb-3 text-primary h1">🎥</div>
<h5 class="fw-bold">دروس مباشرة</h5>
<p class="text-muted">انضم لجلسات تفاعلية عبر Google Meet.</p>
<h5 class="fw-bold">
{% if LANGUAGE_CODE == 'ar' %}دروس مباشرة{% else %}Live Lessons{% endif %}
</h5>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}انضم لجلسات تفاعلية عبر Google Meet.{% else %}Join interactive sessions via Google Meet.{% endif %}
</p>
</div>
</div>
<div class="col-md-4">
<div class="p-4">
<div class="mb-3 text-primary h1">📁</div>
<h5 class="fw-bold">المصادر</h5>
<p class="text-muted">الوصول لمواد الدورة عبر Google Drive.</p>
<h5 class="fw-bold">
{% if LANGUAGE_CODE == 'ar' %}المصادر{% else %}Resources{% endif %}
</h5>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}الوصول لمواد الدورة عبر Google Drive.{% else %}Access course materials via Google Drive.{% endif %}
</p>
</div>
</div>
<div class="col-md-4">
<div class="p-4">
<div class="mb-3 text-primary h1">💳</div>
<h5 class="fw-bold">دفع سهل</h5>
<p class="text-muted">دفع آمن عبر بوابة ثواني.</p>
<h5 class="fw-bold">
{% if LANGUAGE_CODE == 'ar' %}دفع سهل{% else %}Easy Payment{% endif %}
</h5>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}دفع آمن عبر بوابة ثواني.{% else %}Secure payment via Thawani Gateway.{% endif %}
</p>
</div>
</div>
</div>

View File

@ -1,7 +1,9 @@
{% extends 'base.html' %}
{% load i18n static %}
{% block title %}تسجيل الدخول{% endblock %}
{% block title %}
{% if LANGUAGE_CODE == 'ar' %}تسجيل الدخول{% else %}Login{% endif %}
{% endblock %}
{% block content %}
<div class="container hero-section">
@ -9,8 +11,12 @@
<div class="col-md-6 col-lg-5">
<div class="glass-card p-5">
<div class="text-center mb-4">
<h2 class="text-primary fw-bold">مرحباً بعودتك</h2>
<p class="text-muted">سجل الدخول لمتابعة رحلتك التعليمية</p>
<h2 class="text-primary fw-bold">
{% if LANGUAGE_CODE == 'ar' %}مرحباً بعودتك{% else %}Welcome Back{% endif %}
</h2>
<p class="text-muted">
{% if LANGUAGE_CODE == 'ar' %}سجل الدخول لمتابعة رحلتك التعليمية{% else %}Login to continue your educational journey{% endif %}
</p>
</div>
<form method="post">
@ -18,29 +24,32 @@
{% if form.errors %}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
اسم المستخدم أو كلمة المرور غير صحيحة.
{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم أو كلمة المرور غير صحيحة.{% else %}Invalid username or password.{% endif %}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endif %}
<div class="form-floating mb-3">
<input type="text" name="username" autofocus autocapitalize="none" autocomplete="username" maxlength="150" required id="id_username" class="form-control" placeholder="اسم المستخدم">
<label for="id_username"><i class="fas fa-user me-2"></i>اسم المستخدم</label>
<input type="text" name="username" autofocus autocapitalize="none" autocomplete="username" maxlength="150" required id="id_username" class="form-control" placeholder="{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم{% else %}Username{% endif %}">
<label for="id_username"><i class="fas fa-user me-2"></i>{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم{% else %}Username{% endif %}</label>
</div>
<div class="form-floating mb-4">
<input type="password" name="password" autocomplete="current-password" required id="id_password" class="form-control" placeholder="كلمة المرور">
<label for="id_password"><i class="fas fa-lock me-2"></i>كلمة المرور</label>
<input type="password" name="password" autocomplete="current-password" required id="id_password" class="form-control" placeholder="{% if LANGUAGE_CODE == 'ar' %}كلمة المرور{% else %}Password{% endif %}">
<label for="id_password"><i class="fas fa-lock me-2"></i>{% if LANGUAGE_CODE == 'ar' %}كلمة المرور{% else %}Password{% endif %}</label>
</div>
<button type="submit" class="btn btn-primary w-100 py-3 fs-5 fw-bold shadow-sm">
دخول <i class="fas fa-arrow-left ms-2"></i>
{% if LANGUAGE_CODE == 'ar' %}دخول{% else %}Login{% endif %}
<i class="fas fa-arrow-left ms-2"></i>
</button>
<div class="text-center mt-4">
<p class="text-muted mb-0">
ليس لديك حساب؟
<a href="{% url 'register_student' %}" class="text-primary text-decoration-none fw-bold">سجل هنا</a>
{% if LANGUAGE_CODE == 'ar' %}ليس لديك حساب؟{% else %}Don't have an account?{% endif %}
<a href="{% url 'register_student' %}" class="text-primary text-decoration-none fw-bold">
{% if LANGUAGE_CODE == 'ar' %}سجل هنا{% else %}Register here{% endif %}
</a>
</p>
</div>
</form>

View File

@ -0,0 +1,95 @@
(function($) {
'use strict';
$(function() {
console.log("Admin Package JS loaded");
var $levelSelect = $('#id_classroom');
var $subjectSelect = $('#id_subjects');
// Debug selector finding
if (!$levelSelect.length) console.error("Classroom select #id_classroom not found!");
if (!$subjectSelect.length) console.error("Subjects select #id_subjects not found!");
// Check if we are in the admin change form
if (!$levelSelect.length || !$subjectSelect.length) return;
var isArabic = $('html').attr('lang') === 'ar' || $('body').hasClass('rtl');
function updateSubjects(levelId, selectedValues) {
console.log("Updating subjects for level:", levelId);
if (!levelId) {
$subjectSelect.html('');
refreshSelectFilter();
return;
}
$.getJSON('/ajax/get-subjects-by-level/', {level_id: levelId}, function(data) {
console.log("Received subjects:", data);
var options = '';
$.each(data, function(index, subject) {
var selected = '';
if (selectedValues && selectedValues.indexOf(subject.id.toString()) !== -1) {
selected = ' selected';
}
var name = isArabic ? subject.name_ar : subject.name_en;
options += '<option value="' + subject.id + '"' + selected + '>' + name + '</option>';
});
$subjectSelect.html(options);
refreshSelectFilter();
})
.fail(function(jqxhr, textStatus, error) {
console.error("AJAX Error:", textStatus, error);
});
}
function refreshSelectFilter() {
var fieldName = 'subjects';
// Django's filter_horizontal uses SelectFilter2
if (typeof SelectFilter2 !== 'undefined') {
console.log("Refreshing SelectFilter2");
// Remove the existing widget elements
$('.selector').has('#id_' + fieldName + '_from').remove();
// Re-initialize it
SelectFilter2.init('id_' + fieldName, fieldName, false);
} else if (typeof SelectFilter !== 'undefined') {
console.log("Refreshing SelectFilter (Legacy)");
$('.selector').has('#id_' + fieldName + '_from').remove();
SelectFilter.init('id_' + fieldName, fieldName, false);
} else {
console.warn("SelectFilter not found!");
}
}
$levelSelect.on('change', function() {
console.log("Classroom changed to:", $(this).val());
var selectedValues = [];
// Reset subjects when classroom changes
updateSubjects($(this).val(), []);
});
// If we are editing an existing package
if ($levelSelect.val()) {
console.log("Initial load with classroom:", $levelSelect.val());
// Get currently selected values
var selectedValues = [];
// Try to get from the "chosen" side of filter_horizontal if it exists
// Since this runs on page load, standard Django might have already rendered the widget
$('#id_subjects_to option').each(function() {
selectedValues.push($(this).val());
});
// Fallback if widget not yet initialized or for simple select
if (selectedValues.length === 0) {
$subjectSelect.find('option:selected').each(function() {
selectedValues.push($(this).val());
});
}
console.log("Initial selected values:", selectedValues);
updateSubjects($levelSelect.val(), selectedValues);
}
});
})(django.jQuery);

View File

@ -0,0 +1,95 @@
(function($) {
'use strict';
$(function() {
console.log("Admin Package JS loaded");
var $levelSelect = $('#id_classroom');
var $subjectSelect = $('#id_subjects');
// Debug selector finding
if (!$levelSelect.length) console.error("Classroom select #id_classroom not found!");
if (!$subjectSelect.length) console.error("Subjects select #id_subjects not found!");
// Check if we are in the admin change form
if (!$levelSelect.length || !$subjectSelect.length) return;
var isArabic = $('html').attr('lang') === 'ar' || $('body').hasClass('rtl');
function updateSubjects(levelId, selectedValues) {
console.log("Updating subjects for level:", levelId);
if (!levelId) {
$subjectSelect.html('');
refreshSelectFilter();
return;
}
$.getJSON('/ajax/get-subjects-by-level/', {level_id: levelId}, function(data) {
console.log("Received subjects:", data);
var options = '';
$.each(data, function(index, subject) {
var selected = '';
if (selectedValues && selectedValues.indexOf(subject.id.toString()) !== -1) {
selected = ' selected';
}
var name = isArabic ? subject.name_ar : subject.name_en;
options += '<option value="' + subject.id + '"' + selected + '>' + name + '</option>';
});
$subjectSelect.html(options);
refreshSelectFilter();
})
.fail(function(jqxhr, textStatus, error) {
console.error("AJAX Error:", textStatus, error);
});
}
function refreshSelectFilter() {
var fieldName = 'subjects';
// Django's filter_horizontal uses SelectFilter2
if (typeof SelectFilter2 !== 'undefined') {
console.log("Refreshing SelectFilter2");
// Remove the existing widget elements
$('.selector').has('#id_' + fieldName + '_from').remove();
// Re-initialize it
SelectFilter2.init('id_' + fieldName, fieldName, false);
} else if (typeof SelectFilter !== 'undefined') {
console.log("Refreshing SelectFilter (Legacy)");
$('.selector').has('#id_' + fieldName + '_from').remove();
SelectFilter.init('id_' + fieldName, fieldName, false);
} else {
console.warn("SelectFilter not found!");
}
}
$levelSelect.on('change', function() {
console.log("Classroom changed to:", $(this).val());
var selectedValues = [];
// Reset subjects when classroom changes
updateSubjects($(this).val(), []);
});
// If we are editing an existing package
if ($levelSelect.val()) {
console.log("Initial load with classroom:", $levelSelect.val());
// Get currently selected values
var selectedValues = [];
// Try to get from the "chosen" side of filter_horizontal if it exists
// Since this runs on page load, standard Django might have already rendered the widget
$('#id_subjects_to option').each(function() {
selectedValues.push($(this).val());
});
// Fallback if widget not yet initialized or for simple select
if (selectedValues.length === 0) {
$subjectSelect.find('option:selected').each(function() {
selectedValues.push($(this).val());
});
}
console.log("Initial selected values:", selectedValues);
updateSubjects($levelSelect.val(), selectedValues);
}
});
})(django.jQuery);

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB