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.
970 lines
32 KiB
970 lines
32 KiB
from django import forms
|
|
from django.contrib import admin
|
|
from django.utils.translation import gettext_lazy as _
|
|
from unfold.admin import ModelAdmin, TabularInline
|
|
from unfold.contrib.forms.widgets import WysiwygWidget
|
|
from unfold.decorators import display, action
|
|
from utils.json_editor_field import JsonEditorWidget
|
|
import json
|
|
|
|
from utils.admin import dovoodi_admin_site,dovoodi_admin_site
|
|
from ..models import (
|
|
Hadis, HadisReference, HadisTag, HadisStatus, ReferenceImage,
|
|
HadisCollection, HadisInCollection, HadisCorrection
|
|
)
|
|
|
|
|
|
# Custom Forms for JSON Fields
|
|
class HadisAdminForm(forms.ModelForm):
|
|
"""Custom form for Hadis with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = Hadis
|
|
fields = '__all__'
|
|
widgets = {
|
|
'explanation': WysiwygWidget(),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for translation JSON field
|
|
translation_schema = {
|
|
"type": "array",
|
|
"title": "Translations",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Translation",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu"]
|
|
}
|
|
},
|
|
"text": { # <‑‑ use text, not title
|
|
"type": "string",
|
|
"title": "Translation Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"] # <‑‑ update required key
|
|
}
|
|
}
|
|
|
|
# Schema for links JSON field (array of objects with title and link)
|
|
links_schema = {
|
|
"type": "array",
|
|
"title": "Links",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Link",
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"title": "Link Title"
|
|
},
|
|
"link": {
|
|
"type": "string",
|
|
"title": "URL",
|
|
"format": "uri"
|
|
}
|
|
},
|
|
"required": ["title", "link"]
|
|
}
|
|
}
|
|
|
|
# Schema for title_narrator JSON field
|
|
title_narrator_schema = {
|
|
"type": "array",
|
|
"title": "Title Narrators",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title Narrator",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Narrator Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for title JSON field
|
|
title_schema = {
|
|
"type": "array",
|
|
"title": "Titles",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for description JSON field
|
|
description_schema = {
|
|
"type": "array",
|
|
"title": "Descriptions",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Description",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Description Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for hadis_status_text JSON field
|
|
hadis_status_text_schema = {
|
|
"type": "array",
|
|
"title": "Status Texts",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Status Text",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Status Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for address JSON field (text is an array of strings)
|
|
address_schema = {
|
|
"type": "array",
|
|
"title": "Addresses",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Address",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "array",
|
|
"title": "Address Parts",
|
|
"items": {
|
|
"type": "string",
|
|
"title": "Address Part"
|
|
}
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for explanation JSON field (text is an array of objects with title and detail)
|
|
explanation_schema = {
|
|
"type": "array",
|
|
"title": "Explanations",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Explanation",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "array",
|
|
"title": "Explanation Items",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Explanation Item",
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"title": "Title"
|
|
},
|
|
"detail": {
|
|
"type": "string",
|
|
"title": "Detail",
|
|
"format": "textarea"
|
|
}
|
|
},
|
|
"required": ["title", "detail"]
|
|
}
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for explanations JSON field (array of objects with title and description)
|
|
# explanations_schema = {
|
|
# "type": "array",
|
|
# "title": "Explanations",
|
|
# "items": {
|
|
# "type": "object",
|
|
# "title": "Explanation",
|
|
# "properties": {
|
|
# "language_code": {
|
|
# "type": "string",
|
|
# "title": "Language Code",
|
|
# "enum": ["en", "fa", "ar", "ur", "ru"],
|
|
# "options": {
|
|
# "enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
# }
|
|
# },
|
|
# "title": {
|
|
# "type": "string",
|
|
# "title": "Title"
|
|
# },
|
|
# "description": {
|
|
# "type": "string",
|
|
# "title": "Description"
|
|
# }
|
|
# },
|
|
# "required": ["language_code", "title", "description"]
|
|
# }
|
|
# }
|
|
|
|
# Schema for address_details JSON field (array of objects with text and priority)
|
|
# address_details_schema = {
|
|
# "type": "array",
|
|
# "title": "Address Details",
|
|
# "items": {
|
|
# "type": "object",
|
|
# "title": "Address Detail",
|
|
# "properties": {
|
|
# "text": {
|
|
# "type": "string",
|
|
# "title": "Address Text"
|
|
# },
|
|
# "priority": {
|
|
# "type": "integer",
|
|
# "title": "Priority",
|
|
# "minimum": 0
|
|
# }
|
|
# },
|
|
# "required": ["text", "priority"]
|
|
# }
|
|
# }
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['translation'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(translation_schema),
|
|
'title': 'Translations'
|
|
})
|
|
|
|
self.fields['links'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(links_schema),
|
|
'title': 'Links'
|
|
})
|
|
|
|
self.fields['title_narrator'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_narrator_schema),
|
|
'title': 'Title Narrators'
|
|
})
|
|
|
|
self.fields['title'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_schema),
|
|
'title': 'Titles'
|
|
})
|
|
|
|
self.fields['description'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(description_schema),
|
|
'title': 'Descriptions'
|
|
})
|
|
|
|
# self.fields['hadis_status_text'].widget = JsonEditorWidget(attrs={
|
|
# 'schema': json.dumps(hadis_status_text_schema),
|
|
# 'title': 'Status Texts'
|
|
# })
|
|
|
|
self.fields['address'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(address_schema),
|
|
'title': 'Addresses'
|
|
})
|
|
|
|
self.fields['explanation'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(explanation_schema),
|
|
'title': 'Explanations'
|
|
})
|
|
|
|
# self.fields['explanations'].widget = JsonEditorWidget(attrs={
|
|
# 'schema': json.dumps(explanations_schema),
|
|
# 'title': 'Explanations'
|
|
# })
|
|
|
|
# self.fields['address_details'].widget = JsonEditorWidget(attrs={
|
|
# 'schema': json.dumps(address_details_schema),
|
|
# 'title': 'Address Details'
|
|
# })
|
|
|
|
|
|
# Custom Forms for JSON Fields
|
|
class HadisCollectionAdminForm(forms.ModelForm):
|
|
"""Custom form for HadisCollection with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = HadisCollection
|
|
fields = '__all__'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for title JSON field
|
|
title_schema = {
|
|
"type": "array",
|
|
"title": "Titles",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for summary JSON field
|
|
summary_schema = {
|
|
"type": "array",
|
|
"title": "Summaries",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Summary",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Summary Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['title'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_schema),
|
|
'title': 'Titles'
|
|
})
|
|
|
|
self.fields['summary'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(summary_schema),
|
|
'title': 'Summaries'
|
|
})
|
|
|
|
|
|
class HadisTagAdminForm(forms.ModelForm):
|
|
"""Custom form for HadisTag with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = HadisTag
|
|
fields = '__all__'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for title JSON field
|
|
title_schema = {
|
|
"type": "array",
|
|
"title": "Titles",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['title'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_schema),
|
|
'title': 'Titles'
|
|
})
|
|
|
|
|
|
class HadisStatusAdminForm(forms.ModelForm):
|
|
"""Custom form for HadisStatus with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = HadisStatus
|
|
fields = '__all__'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for title JSON field
|
|
title_schema = {
|
|
"type": "array",
|
|
"title": "Titles",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for description JSON field
|
|
description_schema = {
|
|
"type": "array",
|
|
"title": "Descriptions",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Description",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Description Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['title'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_schema),
|
|
'title': 'Titles'
|
|
})
|
|
|
|
self.fields['description'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(description_schema),
|
|
'title': 'Descriptions'
|
|
})
|
|
|
|
|
|
class HadisReferenceAdminForm(forms.ModelForm):
|
|
"""Custom form for HadisReference with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = HadisReference
|
|
fields = '__all__'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for description JSON field
|
|
description_schema = {
|
|
"type": "array",
|
|
"title": "Descriptions",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Description",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Description Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['description'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(description_schema),
|
|
'title': 'Descriptions'
|
|
})
|
|
|
|
|
|
# Inline Admin Classes
|
|
class ReferenceImageInline(TabularInline):
|
|
"""Inline for ReferenceImage in HadisReference admin"""
|
|
model = ReferenceImage
|
|
extra = 0
|
|
fields = ('thumbnail', 'priority')
|
|
ordering = ('priority',)
|
|
|
|
|
|
class HadisReferenceInline(TabularInline):
|
|
"""Inline for HadisReference in Hadis admin"""
|
|
model = HadisReference
|
|
form = HadisReferenceAdminForm
|
|
extra = 0
|
|
fields = ('book_reference', 'description')
|
|
readonly_fields = ('created_at',)
|
|
|
|
|
|
# Main Admin Classes
|
|
class HadisTagAdmin(ModelAdmin):
|
|
"""Admin for HadisTag model"""
|
|
form = HadisTagAdminForm
|
|
list_display = ('get_title_display', 'status', 'created_at')
|
|
list_filter = ('status', 'created_at')
|
|
search_fields = ('title',)
|
|
readonly_fields = ('created_at', 'updated_at')
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('title', 'status')
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at', 'updated_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Title'), ordering='title')
|
|
def get_title_display(self, obj):
|
|
return self._extract_first_text(obj.title)
|
|
|
|
def _extract_first_text(self, json_data):
|
|
"""Helper to safely extract the first 'text' from a JSON list"""
|
|
if json_data and isinstance(json_data, list) and len(json_data) > 0:
|
|
first_item = json_data[0]
|
|
if isinstance(first_item, dict):
|
|
return first_item.get('text', '-')
|
|
return '-'
|
|
|
|
|
|
class HadisStatusAdmin(ModelAdmin):
|
|
"""Admin for HadisStatus model"""
|
|
form = HadisStatusAdminForm
|
|
list_display = ('get_title_display', 'color', 'order', 'get_description_display')
|
|
list_filter = ('color',)
|
|
search_fields = ('title', 'description')
|
|
ordering = ('order',)
|
|
readonly_fields = ('slug',)
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('title', 'slug', 'color', 'order', 'description')
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Title'), ordering='title')
|
|
def get_title_display(self, obj):
|
|
return self._extract_first_text(obj.title)
|
|
|
|
@display(description=_('Description'))
|
|
def get_description_display(self, obj):
|
|
return self._extract_first_text(obj.description)
|
|
|
|
def _extract_first_text(self, json_data):
|
|
"""Helper to safely extract the first 'text' from a JSON list"""
|
|
if json_data and isinstance(json_data, list) and len(json_data) > 0:
|
|
first_item = json_data[0]
|
|
if isinstance(first_item, dict):
|
|
return first_item.get('text', '-')
|
|
return '-'
|
|
|
|
|
|
class HadisAdmin(ModelAdmin):
|
|
"""Admin for Hadis model"""
|
|
form = HadisAdminForm
|
|
list_display = ('number', 'get_title_display', 'category', 'status', 'hadis_status', 'created_at','slug')
|
|
list_filter = ('status', 'hadis_status', 'category', 'created_at')
|
|
search_fields = ('title', 'text', 'category__title', 'slug')
|
|
readonly_fields = ('created_at', 'updated_at', 'share_link', 'slug')
|
|
ordering = ('category', 'number')
|
|
inlines = [HadisReferenceInline]
|
|
filter_horizontal = ('tags',)
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('category', 'number', 'title', 'title_narrator', 'status', 'slug')
|
|
}),
|
|
(_('Content'), {
|
|
'fields': ('text', 'translation', 'explanation','description')
|
|
}),
|
|
(_('Status & Classification'), {
|
|
'fields': ('hadis_status','tags')
|
|
}),
|
|
(_('Additional Information'), {
|
|
'fields': ('address', 'links', 'share_link'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at', 'updated_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Title'), ordering='title')
|
|
def get_title_display(self, obj):
|
|
return self._extract_first_text(obj.title)
|
|
|
|
def _extract_first_text(self, json_data):
|
|
"""Helper to safely extract the first 'text' from a JSON list"""
|
|
if json_data and isinstance(json_data, list) and len(json_data) > 0:
|
|
first_item = json_data[0]
|
|
if isinstance(first_item, dict):
|
|
return first_item.get('text', '-')
|
|
return '-'
|
|
|
|
|
|
class HadisReferenceAdmin(ModelAdmin):
|
|
"""Admin for HadisReference model"""
|
|
form = HadisReferenceAdminForm
|
|
list_display = ('hadis', 'book_reference', 'created_at')
|
|
list_filter = ('created_at', 'book_reference')
|
|
search_fields = ('hadis__title', 'book_reference__title')
|
|
readonly_fields = ('created_at',)
|
|
inlines = [ReferenceImageInline]
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('hadis', 'book_reference','description')
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at',),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
|
|
class ReferenceImageAdmin(ModelAdmin):
|
|
"""Admin for ReferenceImage model"""
|
|
list_display = ('reference', 'thumbnail', 'priority')
|
|
list_filter = ('priority',)
|
|
search_fields = ('reference__hadis__title', 'reference__book__title')
|
|
ordering = ('reference', 'priority')
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('reference', 'thumbnail', 'priority')
|
|
}),
|
|
)
|
|
|
|
|
|
class HadisInCollectionInline(TabularInline):
|
|
"""Inline for HadisInCollection in HadisCollection admin"""
|
|
model = HadisInCollection
|
|
extra = 0
|
|
fields = ('hadis', 'order')
|
|
ordering = ('order',)
|
|
|
|
|
|
class HadisCollectionAdmin(ModelAdmin):
|
|
"""Admin for HadisCollection model"""
|
|
form = HadisCollectionAdminForm
|
|
list_display = ('display_header','get_title_display', 'slug', 'status', 'order', 'created_at')
|
|
list_filter = ('status', 'created_at')
|
|
search_fields = ('title', 'slug', 'summary')
|
|
readonly_fields = ('slug', 'created_at', 'updated_at')
|
|
ordering = ('order',)
|
|
inlines = [HadisInCollectionInline]
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('title', 'slug', 'summary', 'status','pin_top', 'order','thumbnail')
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at', 'updated_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Title'), ordering='title')
|
|
def get_title_display(self, obj):
|
|
return self._extract_first_text(obj.title)
|
|
|
|
def _extract_first_text(self, json_data):
|
|
"""Helper to safely extract the first 'text' from a JSON list"""
|
|
if json_data and isinstance(json_data, list) and len(json_data) > 0:
|
|
first_item = json_data[0]
|
|
if isinstance(first_item, dict):
|
|
return first_item.get('text', '-')
|
|
return '-'
|
|
|
|
@display(description=_("Collection"), header=True)
|
|
def display_header(self, obj):
|
|
from django.templatetags.static import static
|
|
|
|
# Get thumbnail image path - use article's thumbnail if available, otherwise use default
|
|
thumbnail_path = obj.thumbnail.url if obj.thumbnail else None
|
|
|
|
return [
|
|
self.get_title_display(obj),
|
|
None,
|
|
None,
|
|
{
|
|
"path": thumbnail_path,
|
|
"height": 30,
|
|
"width": 50,
|
|
"borderless": True,
|
|
# "squared": True,
|
|
},
|
|
]
|
|
|
|
|
|
|
|
class HadisInCollectionAdmin(ModelAdmin):
|
|
"""Admin for HadisInCollection model"""
|
|
list_display = ('hadis', 'collection', 'order', 'created_at')
|
|
list_filter = ('collection', 'created_at')
|
|
search_fields = ('hadis__title', 'collection__title')
|
|
readonly_fields = ('created_at',)
|
|
ordering = ('collection', 'order')
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('hadis', 'collection', 'order')
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at',),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
|
|
class HadisCorrectionAdminForm(forms.ModelForm):
|
|
"""Custom form for HadisCorrection with JSON editor widgets"""
|
|
|
|
class Meta:
|
|
model = HadisCorrection
|
|
fields = '__all__'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Schema for title JSON field
|
|
title_schema = {
|
|
"type": "array",
|
|
"title": "Titles",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Title",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Title Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for description JSON field
|
|
description_schema = {
|
|
"type": "array",
|
|
"title": "Descriptions",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Description",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Description Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Schema for translation JSON field
|
|
translation_schema = {
|
|
"type": "array",
|
|
"title": "Translations",
|
|
"items": {
|
|
"type": "object",
|
|
"title": "Translation",
|
|
"properties": {
|
|
"language_code": {
|
|
"type": "string",
|
|
"title": "Language Code",
|
|
"enum": ["en", "fa", "ar", "ur", "ru"],
|
|
"options": {
|
|
"enum_titles": ["English", "Persian", "Arabic", "Urdu", "Russian"]
|
|
}
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"title": "Translation Text"
|
|
}
|
|
},
|
|
"required": ["language_code", "text"]
|
|
}
|
|
}
|
|
|
|
# Apply JSON editor widgets
|
|
self.fields['title'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(title_schema),
|
|
'title': 'Titles'
|
|
})
|
|
|
|
self.fields['description'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(description_schema),
|
|
'title': 'Descriptions'
|
|
})
|
|
|
|
self.fields['translation'].widget = JsonEditorWidget(attrs={
|
|
'schema': json.dumps(translation_schema),
|
|
'title': 'Translations'
|
|
})
|
|
|
|
|
|
class HadisCorrectionAdmin(ModelAdmin):
|
|
"""Admin for HadisCorrection model"""
|
|
form = HadisCorrectionAdminForm
|
|
list_display = ('hadis', 'get_title_display', 'slug', 'created_at')
|
|
list_filter = ('created_at', 'hadis__category')
|
|
search_fields = ('hadis__title', 'title', 'slug')
|
|
readonly_fields = ('slug', 'created_at', 'updated_at', 'share_link')
|
|
ordering = ('-created_at',)
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': ('hadis', 'title', 'slug')
|
|
}),
|
|
(_('Content'), {
|
|
'fields': ('description', 'translation')
|
|
}),
|
|
(_('Additional Information'), {
|
|
'fields': ('share_link',),
|
|
'classes': ('collapse',)
|
|
}),
|
|
(_('Timestamps'), {
|
|
'fields': ('created_at', 'updated_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Title'), ordering='title')
|
|
def get_title_display(self, obj):
|
|
return self._extract_first_text(obj.title)
|
|
|
|
def _extract_first_text(self, json_data):
|
|
"""Helper to safely extract the first 'text' from a JSON list"""
|
|
if json_data and isinstance(json_data, list) and len(json_data) > 0:
|
|
first_item = json_data[0]
|
|
if isinstance(first_item, dict):
|
|
return first_item.get('text', '-')
|
|
return '-'
|
|
|
|
|
|
# Register models with dovoodi admin site
|
|
dovoodi_admin_site.register(HadisTag, HadisTagAdmin)
|
|
dovoodi_admin_site.register(HadisStatus, HadisStatusAdmin)
|
|
dovoodi_admin_site.register(Hadis, HadisAdmin)
|
|
dovoodi_admin_site.register(HadisReference, HadisReferenceAdmin)
|
|
dovoodi_admin_site.register(ReferenceImage, ReferenceImageAdmin)
|
|
dovoodi_admin_site.register(HadisCollection, HadisCollectionAdmin)
|
|
dovoodi_admin_site.register(HadisInCollection, HadisInCollectionAdmin)
|
|
dovoodi_admin_site.register(HadisCorrection, HadisCorrectionAdmin)
|