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.
 
 
 
 

218 lines
7.5 KiB

import json
from django.contrib import admin
from django.db import models
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.urls import path
from django.utils.dateformat import format as date_format
from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from dj_language.models import Language
from django import forms
from import_export import fields, widgets, resources
from import_export.admin import ImportExportModelAdmin
from unfold.decorators import display
from unfold.admin import ModelAdmin, TabularInline
from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm
from unfold.contrib.filters.admin import (
RangeDateFilter,
RangeNumericFilter,
SingleNumericFilter,
ChoicesDropdownFilter
)
from apps.dobodbi_calendar.models import CalendarOccasions
from utils.json_editor_field import JsonEditorWidget
from utils.admin import dovoodi_admin_site
from utils.schema import get_calender_dates_schema
class CalendarOccasionsForm(forms.ModelForm):
class Meta:
model = CalendarOccasions
fields = '__all__'
widgets = {
'dates': JsonEditorWidget(attrs={
'schema': get_calender_dates_schema(),
'title': _('Dates'),
}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class CalendarOccasionsAdmin(ModelAdmin):
form = CalendarOccasionsForm
change_list_template = "admin/dobodbi_calendar/calendar_event_list.html"
ordering = ('-id',)
list_display = [
"title",
"display_occasion_type",
"display_event_type",
"is_global",
"is_yearly",
"display_dates",
]
list_filter = [
("occasion_type", ChoicesDropdownFilter),
("event_type", ChoicesDropdownFilter),
"is_global",
"is_yearly",
("created_at", RangeDateFilter),
]
search_fields = [
"title",
"dates",
]
fieldsets = (
("Basic Information", {
"fields": (
"title",
"is_global",
"is_yearly",
"occasion_type",
"event_type",
),
"description": "Main information about the calendar occasion",
}),
("Dates Configuration", {
"fields": ("dates",),
"classes": ("collapse",),
"description": "Configure dates for this occasion",
}),
("Metadata", {
"fields": ("created_at", "updated_at"),
"classes": ("collapse",),
"description": "Metadata information",
}),
)
readonly_fields = ["created_at", "updated_at"]
# سفارشی‌سازی اکشن‌ها
actions = ["make_global", "make_not_global"]
# متدهای اکشن
@admin.action(description="Mark selected occasions as global")
def make_global(self, request, queryset):
queryset.update(is_global=True)
@admin.action(description="Mark selected occasions as not global")
def make_not_global(self, request, queryset):
queryset.update(is_global=False)
@display(description="Occasion Type", label=True)
def display_occasion_type(self, obj):
return obj.get_occasion_type_display()
@display(description="Event Type", label=True)
def display_event_type(self, obj):
return obj.get_event_type_display()
@display(description="Dates")
def display_dates(self, obj):
from django.utils.html import format_html
return "\n".join([f"{i['month']}/{i['day']}" for i in obj.dates])
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path(
"manage/create/",
self.admin_site.admin_view(self.create_event_view),
name="dobodbi_calendar_calendaroccasions_create",
),
path(
"manage/<int:event_id>/update/",
self.admin_site.admin_view(self.update_event_view),
name="dobodbi_calendar_calendaroccasions_update",
),
]
return custom_urls + urls
def changelist_view(self, request, extra_context=None):
events = CalendarOccasions.objects.all().order_by("-updated_at", "-id")
event_rows = [
{
"id": event.id,
"title": event.title,
"occasion_type": event.occasion_type,
"occasion_type_label": event.get_occasion_type_display(),
"event_type": event.event_type or "",
"event_type_label": event.get_event_type_display() if event.event_type else "-",
"is_global": event.is_global,
"is_yearly": event.is_yearly,
"dates": event.dates or [],
"dates_preview": ", ".join(
[
f"{date_item.get('year', '')}/{date_item.get('month', '')}/{date_item.get('day', '')}".strip("/")
for date_item in (event.dates or [])
]
),
"updated_at": date_format(event.updated_at, "Y-m-d H:i"),
"created_at": date_format(event.created_at, "Y-m-d H:i"),
}
for event in events
]
extra_context = extra_context or {}
extra_context.update(
{
"calendar_events": event_rows,
"calendar_event_type_choices": [
{"value": value, "label": label}
for value, label in CalendarOccasions.EventType.choices
],
"calendar_occasion_type_choices": [
{"value": value, "label": label}
for value, label in CalendarOccasions.OccasionType.choices
],
}
)
return super().changelist_view(request, extra_context=extra_context)
def create_event_view(self, request):
if request.method != "POST":
return JsonResponse({"ok": False, "error": "Method not allowed."}, status=405)
form = CalendarOccasionsForm(request.POST)
if form.is_valid():
event = form.save()
return JsonResponse({"ok": True, "id": event.id})
return JsonResponse({"ok": False, "errors": form.errors.get_json_data()}, status=400)
def update_event_view(self, request, event_id):
if request.method != "POST":
return JsonResponse({"ok": False, "error": "Method not allowed."}, status=405)
event = get_object_or_404(CalendarOccasions, pk=event_id)
form = CalendarOccasionsForm(request.POST, instance=event)
if form.is_valid():
form.save()
return JsonResponse({"ok": True, "id": event.id})
return JsonResponse({"ok": False, "errors": form.errors.get_json_data()}, status=400)
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
try:
# امکان جستجو در فیلد JSON
import json
json.loads(search_term)
queryset |= self.model.objects.filter(dates__contains=search_term)
except ValueError:
pass
return queryset, use_distinct
dovoodi_admin_site.register(CalendarOccasions, CalendarOccasionsAdmin)