from django.contrib import admin from django.utils.translation import gettext_lazy as _ from unfold.admin import ModelAdmin, TabularInline, StackedInline from unfold.decorators import display, action from apps.projects.models.project import ( Project, KanbanColumn, KanbanTask, ProjectDocument, ) from utils.admin import project_admin_site class KanbanTaskInline(TabularInline): model = KanbanTask extra = 0 fields = ('title', 'column', 'priority', 'assignee', 'due_date', 'order') class ProjectDocumentInline(TabularInline): model = ProjectDocument extra = 0 fields = ('title', 'file', 'doc_type', 'uploaded_at') readonly_fields = ('uploaded_at',) @admin.register(Project, site=project_admin_site) class ProjectAdmin(ModelAdmin): list_display = ( 'title', 'owner_institution', 'category', 'status_badge', 'progress_percentage_display', 'budget', 'team_size', 'start_date', 'estimated_end_date', ) list_display_links = ('title', 'owner_institution', 'category') list_filter = ('status', 'category', 'owner_institution') search_fields = ('title', 'description', 'owner_institution__name') prepopulated_fields = {'slug': ('title',)} filter_horizontal = ('collaborating_institutions',) inlines = [KanbanTaskInline, ProjectDocumentInline] actions = ['mark_as_completed', 'mark_as_active'] fieldsets = ( (_('Project Definition'), { 'fields': ('title', 'slug', 'description', 'category', 'status') }), (_('Institutional Governance'), { 'fields': ('owner_institution', 'collaborating_institutions', 'created_by') }), (_('Progress & Budget'), { 'fields': ('progress_percentage', 'budget', 'team_size', 'cover_image') }), (_('Timeline Schedule'), { 'fields': ('start_date', 'estimated_end_date', 'actual_end_date') }), ) @display(description=_('Status'), label={ Project.Status.ACTIVE: "info", Project.Status.COMPLETED: "success", Project.Status.PLANNING: "warning", Project.Status.ON_HOLD: "danger", }) def status_badge(self, obj): return obj.get_status_display() @display(description=_('Progress')) def progress_percentage_display(self, obj): return f"{obj.progress_percentage}%" @action(description=_('Mark selected projects as Completed')) def mark_as_completed(self, request, queryset): count = queryset.update(status=Project.Status.COMPLETED, progress_percentage=100) self.message_user(request, _(f"{count} project(s) marked as completed.")) @action(description=_('Mark selected projects as Active')) def mark_as_active(self, request, queryset): count = queryset.update(status=Project.Status.ACTIVE) self.message_user(request, _(f"{count} project(s) marked as active.")) @admin.register(KanbanColumn, site=project_admin_site) class KanbanColumnAdmin(ModelAdmin): list_display = ('name', 'project', 'code', 'order', 'color') list_display_links = ('name', 'project', 'code') list_filter = ('project',) search_fields = ('name', 'project__title') @admin.register(KanbanTask, site=project_admin_site) class KanbanTaskAdmin(ModelAdmin): list_display = ('title', 'project', 'column', 'priority_badge', 'assignee', 'due_date', 'order') list_display_links = ('title', 'project', 'column', 'assignee') list_filter = ('priority', 'project', 'column') search_fields = ('title', 'description', 'project__title', 'assignee__fullname') @display(description=_('Priority'), label={ KanbanTask.Priority.URGENT: "danger", KanbanTask.Priority.HIGH: "warning", KanbanTask.Priority.MEDIUM: "info", KanbanTask.Priority.LOW: "success", }) def priority_badge(self, obj): return obj.get_priority_display() @admin.register(ProjectDocument, site=project_admin_site) class ProjectDocumentAdmin(ModelAdmin): list_display = ('title', 'project', 'doc_type', 'uploaded_by', 'uploaded_at') list_display_links = ('title', 'project') list_filter = ('doc_type', 'uploaded_at') search_fields = ('title', 'project__title') readonly_fields = ('uploaded_at',)