update
This commit is contained in:
149
gnx-react/backend/career/admin.py
Normal file
149
gnx-react/backend/career/admin.py
Normal file
@@ -0,0 +1,149 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from .models import JobPosition, JobApplication
|
||||
|
||||
|
||||
@admin.register(JobPosition)
|
||||
class JobPositionAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
'title',
|
||||
'department',
|
||||
'location',
|
||||
'open_positions',
|
||||
'employment_type',
|
||||
'status_badge',
|
||||
'featured',
|
||||
'posted_date',
|
||||
'applications_count'
|
||||
]
|
||||
list_filter = ['status', 'employment_type', 'location_type', 'featured', 'department', 'posted_date']
|
||||
search_fields = ['title', 'department', 'location', 'short_description']
|
||||
prepopulated_fields = {'slug': ('title',)}
|
||||
readonly_fields = ['posted_date', 'updated_date', 'applications_count']
|
||||
|
||||
fieldsets = (
|
||||
('Basic Information', {
|
||||
'fields': ('title', 'slug', 'department', 'status', 'featured', 'priority')
|
||||
}),
|
||||
('Employment Details', {
|
||||
'fields': ('employment_type', 'location_type', 'location', 'open_positions', 'experience_required')
|
||||
}),
|
||||
('Salary Information', {
|
||||
'fields': ('salary_min', 'salary_max', 'salary_currency', 'salary_period', 'salary_additional')
|
||||
}),
|
||||
('Job Description', {
|
||||
'fields': ('short_description', 'about_role')
|
||||
}),
|
||||
('Requirements & Qualifications', {
|
||||
'fields': ('requirements', 'responsibilities', 'qualifications', 'bonus_points', 'benefits'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Dates', {
|
||||
'fields': ('start_date', 'deadline', 'posted_date', 'updated_date')
|
||||
}),
|
||||
)
|
||||
|
||||
def status_badge(self, obj):
|
||||
colors = {
|
||||
'active': 'green',
|
||||
'closed': 'red',
|
||||
'draft': 'orange'
|
||||
}
|
||||
return format_html(
|
||||
'<span style="color: {}; font-weight: bold;">{}</span>',
|
||||
colors.get(obj.status, 'black'),
|
||||
obj.get_status_display()
|
||||
)
|
||||
status_badge.short_description = 'Status'
|
||||
|
||||
def applications_count(self, obj):
|
||||
count = obj.applications.count()
|
||||
return format_html(
|
||||
'<span style="font-weight: bold;">{} application(s)</span>',
|
||||
count
|
||||
)
|
||||
applications_count.short_description = 'Applications'
|
||||
|
||||
|
||||
@admin.register(JobApplication)
|
||||
class JobApplicationAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
'full_name',
|
||||
'email',
|
||||
'job',
|
||||
'status_badge',
|
||||
'applied_date',
|
||||
'resume_link'
|
||||
]
|
||||
list_filter = ['status', 'job', 'applied_date']
|
||||
search_fields = ['first_name', 'last_name', 'email', 'job__title']
|
||||
readonly_fields = ['applied_date', 'updated_date', 'resume_link']
|
||||
|
||||
fieldsets = (
|
||||
('Job Information', {
|
||||
'fields': ('job', 'status')
|
||||
}),
|
||||
('Applicant Information', {
|
||||
'fields': ('first_name', 'last_name', 'email', 'phone')
|
||||
}),
|
||||
('Professional Information', {
|
||||
'fields': ('current_position', 'current_company', 'years_of_experience')
|
||||
}),
|
||||
('Application Details', {
|
||||
'fields': ('cover_letter', 'resume', 'resume_link', 'portfolio_url')
|
||||
}),
|
||||
('Social Links', {
|
||||
'fields': ('linkedin_url', 'github_url', 'website_url'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Availability & Salary', {
|
||||
'fields': ('available_from', 'notice_period', 'expected_salary', 'salary_currency'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('applied_date', 'updated_date', 'consent', 'notes')
|
||||
}),
|
||||
)
|
||||
|
||||
def status_badge(self, obj):
|
||||
colors = {
|
||||
'new': 'blue',
|
||||
'reviewing': 'orange',
|
||||
'shortlisted': 'purple',
|
||||
'interviewed': 'teal',
|
||||
'accepted': 'green',
|
||||
'rejected': 'red'
|
||||
}
|
||||
return format_html(
|
||||
'<span style="color: {}; font-weight: bold;">{}</span>',
|
||||
colors.get(obj.status, 'black'),
|
||||
obj.get_status_display()
|
||||
)
|
||||
status_badge.short_description = 'Status'
|
||||
|
||||
def resume_link(self, obj):
|
||||
if obj.resume:
|
||||
return format_html(
|
||||
'<a href="{}" target="_blank">Download Resume</a>',
|
||||
obj.resume.url
|
||||
)
|
||||
return '-'
|
||||
resume_link.short_description = 'Resume'
|
||||
|
||||
actions = ['mark_as_reviewing', 'mark_as_shortlisted', 'mark_as_rejected']
|
||||
|
||||
def mark_as_reviewing(self, request, queryset):
|
||||
queryset.update(status='reviewing')
|
||||
self.message_user(request, f'{queryset.count()} application(s) marked as reviewing.')
|
||||
mark_as_reviewing.short_description = 'Mark as Reviewing'
|
||||
|
||||
def mark_as_shortlisted(self, request, queryset):
|
||||
queryset.update(status='shortlisted')
|
||||
self.message_user(request, f'{queryset.count()} application(s) marked as shortlisted.')
|
||||
mark_as_shortlisted.short_description = 'Mark as Shortlisted'
|
||||
|
||||
def mark_as_rejected(self, request, queryset):
|
||||
queryset.update(status='rejected')
|
||||
self.message_user(request, f'{queryset.count()} application(s) marked as rejected.')
|
||||
mark_as_rejected.short_description = 'Mark as Rejected'
|
||||
|
||||
Reference in New Issue
Block a user