Initial project
This commit is contained in:
186
surveys/admin.py
Normal file
186
surveys/admin.py
Normal file
@@ -0,0 +1,186 @@
|
||||
from django.contrib import admin
|
||||
from django.urls import reverse
|
||||
from django.utils.html import format_html
|
||||
|
||||
from .models import Survey, SurveyAnswer, SurveyChoice, SurveyQuestion, SurveyResponse
|
||||
|
||||
|
||||
class SurveyAdminThemeMixin:
|
||||
class Media:
|
||||
css = {"all": ("surveys/admin.css",)}
|
||||
|
||||
|
||||
class SurveyQuestionInline(SurveyAdminThemeMixin, admin.StackedInline):
|
||||
model = SurveyQuestion
|
||||
extra = 1
|
||||
show_change_link = True
|
||||
prepopulated_fields = {"slug": ("prompt",)}
|
||||
fields = (
|
||||
("position", "type", "is_required"),
|
||||
"prompt",
|
||||
"slug",
|
||||
"help_text",
|
||||
("min_value", "max_value"),
|
||||
)
|
||||
|
||||
|
||||
class SurveyChoiceInline(SurveyAdminThemeMixin, admin.TabularInline):
|
||||
model = SurveyChoice
|
||||
extra = 2
|
||||
fields = ("position", "label", "value")
|
||||
prepopulated_fields = {"value": ("label",)}
|
||||
|
||||
|
||||
class SurveyAnswerInline(admin.TabularInline):
|
||||
model = SurveyAnswer
|
||||
extra = 0
|
||||
can_delete = False
|
||||
fields = ("question", "value", "selected_choices_display")
|
||||
readonly_fields = fields
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
@admin.display(description="Selected choices")
|
||||
def selected_choices_display(self, obj):
|
||||
labels = [choice.label for choice in obj.selected_choices.all()]
|
||||
return ", ".join(labels) or "-"
|
||||
|
||||
|
||||
@admin.register(Survey)
|
||||
class SurveyAdmin(SurveyAdminThemeMixin, admin.ModelAdmin):
|
||||
list_display = (
|
||||
"title",
|
||||
"status",
|
||||
"starts_at",
|
||||
"ends_at",
|
||||
"response_count",
|
||||
"api_link",
|
||||
)
|
||||
list_filter = ("status", "starts_at", "ends_at")
|
||||
search_fields = ("title", "description", "slug")
|
||||
prepopulated_fields = {"slug": ("title",)}
|
||||
readonly_fields = ("created_at", "updated_at", "response_count", "api_link")
|
||||
inlines = [SurveyQuestionInline]
|
||||
actions = ("publish_surveys", "close_surveys")
|
||||
fieldsets = (
|
||||
(
|
||||
"Survey",
|
||||
{
|
||||
"fields": (
|
||||
"title",
|
||||
"slug",
|
||||
"description",
|
||||
"thank_you_message",
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
"Publishing",
|
||||
{
|
||||
"fields": (
|
||||
"status",
|
||||
"starts_at",
|
||||
"ends_at",
|
||||
"allow_multiple_responses",
|
||||
"api_link",
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
"System",
|
||||
{
|
||||
"fields": ("response_count", "created_at", "updated_at"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@admin.display(description="Responses")
|
||||
def response_count(self, obj):
|
||||
if not obj.pk:
|
||||
return 0
|
||||
return obj.responses.count()
|
||||
|
||||
@admin.display(description="Public API")
|
||||
def api_link(self, obj):
|
||||
if not obj.pk:
|
||||
return "-"
|
||||
url = reverse("survey-detail", args=[obj.slug])
|
||||
return format_html('<a class="button" href="{}" target="_blank">Open API</a>', url)
|
||||
|
||||
@admin.action(description="Publish selected surveys")
|
||||
def publish_surveys(self, request, queryset):
|
||||
queryset.update(status=Survey.Status.PUBLISHED)
|
||||
|
||||
@admin.action(description="Close selected surveys")
|
||||
def close_surveys(self, request, queryset):
|
||||
queryset.update(status=Survey.Status.CLOSED)
|
||||
|
||||
|
||||
@admin.register(SurveyQuestion)
|
||||
class SurveyQuestionAdmin(SurveyAdminThemeMixin, admin.ModelAdmin):
|
||||
list_display = ("prompt", "survey", "type", "is_required", "position")
|
||||
list_filter = ("type", "is_required", "survey__status")
|
||||
search_fields = ("prompt", "slug", "survey__title")
|
||||
prepopulated_fields = {"slug": ("prompt",)}
|
||||
inlines = [SurveyChoiceInline]
|
||||
fieldsets = (
|
||||
(
|
||||
"Question",
|
||||
{
|
||||
"fields": (
|
||||
"survey",
|
||||
"prompt",
|
||||
"slug",
|
||||
"type",
|
||||
"help_text",
|
||||
"is_required",
|
||||
"position",
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
"Rating Options",
|
||||
{
|
||||
"fields": ("min_value", "max_value"),
|
||||
"description": "Used only for rating questions.",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(SurveyChoice)
|
||||
class SurveyChoiceAdmin(SurveyAdminThemeMixin, admin.ModelAdmin):
|
||||
list_display = ("label", "question", "survey_title", "value", "position")
|
||||
list_filter = ("question__survey",)
|
||||
search_fields = ("label", "value", "question__prompt", "question__survey__title")
|
||||
prepopulated_fields = {"value": ("label",)}
|
||||
|
||||
@admin.display(description="Survey")
|
||||
def survey_title(self, obj):
|
||||
return obj.question.survey.title
|
||||
|
||||
|
||||
@admin.register(SurveyResponse)
|
||||
class SurveyResponseAdmin(SurveyAdminThemeMixin, admin.ModelAdmin):
|
||||
list_display = ("survey", "respondent_email", "submitted_at", "ip_address")
|
||||
list_filter = ("survey", "submitted_at")
|
||||
search_fields = ("survey__title", "respondent_email", "ip_address")
|
||||
readonly_fields = (
|
||||
"survey",
|
||||
"respondent_email",
|
||||
"metadata",
|
||||
"ip_address",
|
||||
"user_agent",
|
||||
"submitted_at",
|
||||
)
|
||||
inlines = [SurveyAnswerInline]
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
|
||||
admin.site.site_header = "Survey Studio"
|
||||
admin.site.site_title = "Survey Studio"
|
||||
admin.site.index_title = "Survey Management"
|
||||
Reference in New Issue
Block a user