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.
115 lines
4.0 KiB
115 lines
4.0 KiB
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_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_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_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_filter = ('doc_type', 'uploaded_at')
|
|
search_fields = ('title', 'project__title')
|
|
readonly_fields = ('uploaded_at',)
|