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.
222 lines
8.7 KiB
222 lines
8.7 KiB
from django.contrib import admin
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.http import JsonResponse
|
|
from django.urls import path
|
|
from django.db import models
|
|
from django.contrib import messages
|
|
from django.http import HttpResponseRedirect
|
|
from django.urls import reverse
|
|
|
|
from unfold.admin import ModelAdmin
|
|
from unfold.decorators import display
|
|
|
|
from dj_category.admin import BaseCategoryAdmin
|
|
from ajaxdatatable.admin import AjaxDatatable
|
|
from django.db.models import Case, When, Value
|
|
from django.utils.html import format_html
|
|
|
|
from apps.hadis.models import HadisCategory
|
|
from utils.admin import project_admin_site
|
|
|
|
|
|
@admin.register(HadisCategory)
|
|
class HadisCategoryAdmin(BaseCategoryAdmin, ModelAdmin):
|
|
change_form_template = 'admin/hadiscategory/change_form.html'
|
|
change_list_template = 'admin/category_index.html'
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('name', 'source_type', 'category_type', 'parent', 'is_active', 'order'),
|
|
'classes': ('unfold-fieldset',),
|
|
}),
|
|
)
|
|
|
|
search_fields = ['name']
|
|
list_display = ['name', 'source_type_badge', 'category_type', 'parent', 'is_active', 'order']
|
|
list_filter = ['source_type', 'category_type', 'is_active']
|
|
|
|
@display(description=_("Source Type"))
|
|
def source_type_badge(self, obj):
|
|
badge_classes = {
|
|
'quran': 'unfold-badge unfold-badge--success',
|
|
'hadith': 'unfold-badge unfold-badge--info',
|
|
'book': 'unfold-badge unfold-badge--warning',
|
|
# Add more source types as needed
|
|
}
|
|
badge_class = badge_classes.get(obj.source_type, 'unfold-badge')
|
|
return format_html('<span class="{}">{}</span>', badge_class, obj.get_source_type_display())
|
|
|
|
def get_form(self, request, obj=None, **kwargs):
|
|
form = super().get_form(request, obj, **kwargs)
|
|
return form
|
|
|
|
def get_urls(self):
|
|
urls = super().get_urls()
|
|
custom_urls = [
|
|
path('categories-ajax/hadiscategory/', self.admin_site.admin_view(self.ajax_categories), name='hadiscategory_ajax_categories'),
|
|
]
|
|
return custom_urls + urls
|
|
|
|
def get_categories_groupby_language(self, request=None, selected_values=(), is_multiple=False):
|
|
return super().get_categories(request, selected_values, is_multiple)
|
|
|
|
def ajax_update(self, request):
|
|
data = request.POST
|
|
src_node = self.model.objects.get(pk=int(data['srcNode']))
|
|
other_node = self.model.objects.get(pk=int(data['otherNode']))
|
|
|
|
if src_node.slug in self.base_categories or other_node.slug in self.base_categories:
|
|
return JsonResponse({'data': _('This item can not be modified')}, status=401)
|
|
|
|
mode = data['hitMode']
|
|
if mode == 'over':
|
|
src_node.move_to(other_node, 'first-child')
|
|
elif mode == 'after':
|
|
src_node.move_to(other_node, 'right')
|
|
elif mode == 'before':
|
|
src_node.move_to(other_node, 'left')
|
|
|
|
return JsonResponse({'data': 'ok'}, safe=False)
|
|
|
|
def get_categories(self, request=None, selected_values=(), is_multiple=False):
|
|
"""
|
|
Override the get_categories method to filter by source_type if provided in the request
|
|
"""
|
|
categories = super().get_categories(request, selected_values, is_multiple)
|
|
|
|
# If request has source_type parameter, filter the categories
|
|
if request and request.GET.get('source_type'):
|
|
source_type = request.GET.get('source_type')
|
|
# Filter the categories by source_type
|
|
filtered_categories = []
|
|
for category in categories:
|
|
# If it's a dictionary (serialized category)
|
|
if isinstance(category, dict) and category.get('source_type') == source_type:
|
|
filtered_categories.append(category)
|
|
# If it's a model instance
|
|
elif hasattr(category, 'source_type') and getattr(category, 'source_type') == source_type:
|
|
filtered_categories.append(category)
|
|
return filtered_categories
|
|
|
|
return categories
|
|
|
|
def ajax_categories(self, request):
|
|
"""
|
|
Handle AJAX request for categories with source_type filtering and search
|
|
"""
|
|
# Get source_type from request
|
|
source_type = request.GET.get('source_type')
|
|
|
|
# Get node_id if provided (for single node data)
|
|
node_id = request.GET.get('node_id')
|
|
|
|
# Get search term if provided
|
|
search = request.GET.get('search')
|
|
|
|
# Get parent level filter if provided
|
|
parent_level = request.GET.get('parent_level')
|
|
|
|
if node_id:
|
|
# Return data for a specific node
|
|
try:
|
|
node = self.model.objects.get(pk=int(node_id))
|
|
return JsonResponse({
|
|
'id': node.id,
|
|
'source_type': node.source_type,
|
|
'category_type': node.category_type,
|
|
'parent': node.parent_id,
|
|
'level': node.level_p # Add the level_p property
|
|
})
|
|
except self.model.DoesNotExist:
|
|
return JsonResponse({'error': 'Node not found'}, status=404)
|
|
|
|
# Get all categories
|
|
queryset = self.model.objects.all()
|
|
|
|
# Annotate queryset with level_p
|
|
queryset = queryset.annotate(
|
|
level_pp=Case(
|
|
When(parent=None, then=Value(1)),
|
|
When(parent__isnull=False, parent__parent=None, then=Value(2)),
|
|
default=Value(3),
|
|
output_field=models.IntegerField()
|
|
)
|
|
)
|
|
|
|
# Filter by source_type if provided
|
|
if source_type:
|
|
queryset = queryset.filter(source_type=source_type)
|
|
|
|
# Filter by search term if provided
|
|
if search:
|
|
queryset = queryset.filter(name__icontains=search)
|
|
|
|
# Filter by parent_level if provided
|
|
if parent_level and parent_level.isdigit():
|
|
# Convert to integer
|
|
level = int(parent_level)
|
|
# Filter categories by level_p
|
|
queryset = queryset.filter(level_pp=level)
|
|
|
|
# Convert queryset to list of dictionaries for JSON response
|
|
categories = []
|
|
for category in queryset:
|
|
categories.append({
|
|
'key': category.id,
|
|
'title': category.name,
|
|
'parent': category.parent_id,
|
|
'source_type': category.source_type,
|
|
'category_type': category.category_type,
|
|
'level': category.level_p,
|
|
# Add data property to store additional information
|
|
'data': {
|
|
'parent': category.parent_id,
|
|
'level': category.level_p
|
|
}
|
|
})
|
|
|
|
return JsonResponse(categories, safe=False)
|
|
|
|
def save_model(self, request, obj, form, change):
|
|
# Get the level choice from the form data
|
|
level_choice = request.POST.get('level_choice_hidden')
|
|
|
|
# Get the parent from AJAX selection if provided
|
|
ajax_parent = request.POST.get('ajax_parent')
|
|
if ajax_parent and ajax_parent.isdigit():
|
|
# Set the parent for the object
|
|
try:
|
|
parent_category = self.model.objects.get(pk=int(ajax_parent))
|
|
obj.parent = parent_category
|
|
except self.model.DoesNotExist:
|
|
pass
|
|
|
|
# Let the parent class handle the save
|
|
super().save_model(request, obj, form, change)
|
|
|
|
# Add a message to trigger tree reload via JavaScript
|
|
messages.success(request, _("Category saved successfully. Tree will be reloaded."),
|
|
extra_tags='unfold-message unfold-message--success')
|
|
|
|
# Set a flag in the request to redirect back to the category index page
|
|
request._category_saved = True
|
|
|
|
def response_add(self, request, obj, post_url_continue=None):
|
|
"""
|
|
Override to redirect back to the category index page after adding a new category
|
|
"""
|
|
if hasattr(request, '_category_saved') and request._category_saved:
|
|
return HttpResponseRedirect(reverse('admin:hadis_hadiscategory_changelist'))
|
|
return super().response_add(request, obj, post_url_continue)
|
|
|
|
def response_change(self, request, obj):
|
|
"""
|
|
Override to redirect back to the category index page after editing a category
|
|
"""
|
|
if hasattr(request, '_category_saved') and request._category_saved:
|
|
return HttpResponseRedirect(reverse('admin:hadis_hadiscategory_changelist'))
|
|
return super().response_change(request, obj)
|
|
|
|
|
|
# Register with project_admin_site if needed
|
|
# project_admin_site.register(HadisCategory, HadisCategoryAdmin)
|