@@ -1,155 +0,0 @@
|
|||||||
# Django Admin Implementation Status
|
|
||||||
|
|
||||||
**Last Updated:** December 14, 2025
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase Completion Status
|
|
||||||
|
|
||||||
### ✅ Phase 0: Foundation - COMPLETED (Dec 14, 2025)
|
|
||||||
|
|
||||||
**What was completed:**
|
|
||||||
- [x] Installed django-unfold==0.73.1
|
|
||||||
- [x] Configured UNFOLD settings in settings.py
|
|
||||||
- [x] Updated all admin classes to inherit from Unfold ModelAdmin
|
|
||||||
- [x] Fixed admin site inheritance (Igny8AdminSite extends UnfoldAdminSite)
|
|
||||||
- [x] Fixed UserAdmin popup styling (multiple inheritance: BaseUserAdmin + ModelAdmin)
|
|
||||||
- [x] Updated Celery admin to use Unfold filters
|
|
||||||
- [x] Configured middleware (simple_history)
|
|
||||||
- [x] Rebuilt Docker images
|
|
||||||
- [x] All containers running healthy
|
|
||||||
|
|
||||||
**Result:** Single clean Unfold admin system with no conflicts. All styling handled by Unfold automatically.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ Phase 1: Configuration Cleanup - COMPLETED (Dec 14, 2025)
|
|
||||||
|
|
||||||
**Completed:**
|
|
||||||
- [x] UserAdmin popup styling fix
|
|
||||||
- [x] Verified no unused site_building models in site.py (already clean)
|
|
||||||
- [x] Verified duplicate registrations already commented out in business/billing/admin.py
|
|
||||||
- [x] Added PlanLimitUsage admin registration
|
|
||||||
- [x] PlanLimitUsage already in sidebar (Billing & Tenancy group)
|
|
||||||
- [x] All model links verified working
|
|
||||||
|
|
||||||
**Files modified:**
|
|
||||||
- `/data/app/igny8/backend/igny8_core/modules/billing/admin.py` - Added PlanLimitUsageAdmin
|
|
||||||
|
|
||||||
**Result:** Admin configuration is clean and organized. All models properly registered and grouped.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ Phase 2: Bulk Operations & Export - COMPLETED (Dec 14, 2025)
|
|
||||||
|
|
||||||
**Completed:**
|
|
||||||
- [x] Added ExportMixin to Keywords admin (already had export)
|
|
||||||
- [x] Created KeywordsResource class for export configuration
|
|
||||||
- [x] Added Unfold advanced filters to Tasks admin (ChoicesDropdownFilter, RelatedDropdownFilter, RangeDateFilter)
|
|
||||||
- [x] Added Unfold advanced filters to Content admin (RangeNumericFilter for word_count, enhanced search)
|
|
||||||
- [x] Added Unfold advanced filters to Keywords admin (RangeNumericFilter for volume/difficulty, full filter set)
|
|
||||||
- [x] Added Unfold advanced filters to Clusters admin (RangeNumericFilter, RangeDateFilter)
|
|
||||||
- [x] Added Unfold advanced filters to ContentIdeas admin (comprehensive filter set)
|
|
||||||
- [x] Verified existing bulk actions (Tasks: status changes, Content: status changes, Keywords: cluster assignment)
|
|
||||||
- [x] Backend restarted successfully
|
|
||||||
|
|
||||||
**Files modified:**
|
|
||||||
- `/data/app/igny8/backend/igny8_core/modules/writer/admin.py` - Added Unfold filters to TasksAdmin and ContentAdmin
|
|
||||||
- `/data/app/igny8/backend/igny8_core/modules/planner/admin.py` - Added Unfold filters to KeywordsAdmin, ClustersAdmin, ContentIdeasAdmin
|
|
||||||
|
|
||||||
**Result:** Admin interfaces now have modern date range pickers, numeric sliders, and searchable dropdowns. Better UX for filtering large datasets.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ⚪ Phase 3: Monitoring & Dashboards - NOT STARTED
|
|
||||||
|
|
||||||
**Tasks:**
|
|
||||||
- [ ] Create Celery task monitoring admin
|
|
||||||
- [ ] Create custom dashboard view with metrics
|
|
||||||
- [ ] Create dashboard template
|
|
||||||
- [ ] Add account health indicators
|
|
||||||
- [ ] Create alert system
|
|
||||||
- [ ] Add dashboard route to admin URLs
|
|
||||||
|
|
||||||
**Estimated effort:** 1-2 weeks
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ⚪ Phase 4: Analytics & Reporting - NOT STARTED
|
|
||||||
|
|
||||||
**Tasks:**
|
|
||||||
- [ ] Create reports module (revenue, usage, content, data quality)
|
|
||||||
- [ ] Create report templates
|
|
||||||
- [ ] Add chart visualizations
|
|
||||||
- [ ] Add report links to admin navigation
|
|
||||||
- [ ] Optimize report queries
|
|
||||||
|
|
||||||
**Estimated effort:** 1 week
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ⚪ Phase 5: Advanced Features - NOT STARTED
|
|
||||||
|
|
||||||
**Tasks:**
|
|
||||||
- [ ] Enable list_editable for Tasks and Keywords
|
|
||||||
- [ ] Add HistoricalRecords to critical models
|
|
||||||
- [ ] Create permission groups management command
|
|
||||||
- [ ] Test permission restrictions
|
|
||||||
|
|
||||||
**Estimated effort:** 1 week
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Achievements
|
|
||||||
|
|
||||||
1. **✅ NO Custom CSS/Styling Needed**
|
|
||||||
- Unfold handles all UI/UX automatically
|
|
||||||
- Modern Tailwind-based design out of the box
|
|
||||||
- Dark mode support built-in
|
|
||||||
- Responsive layout automatic
|
|
||||||
|
|
||||||
2. **✅ UserAdmin Popup Fix**
|
|
||||||
- Fixed popup forms to use Unfold templates
|
|
||||||
- Multiple inheritance: `class UserAdmin(BaseUserAdmin, ModelAdmin)`
|
|
||||||
- All popups now consistent with main admin styling
|
|
||||||
|
|
||||||
3. **✅ Clean Architecture**
|
|
||||||
- Single admin system (Unfold only)
|
|
||||||
- No conflicts between themes
|
|
||||||
- All containers healthy
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
### Immediate (Next):
|
|
||||||
1. **✅ Phase 2 Complete** - Move to Phase 3
|
|
||||||
2. Start Phase 3: Monitoring & Dashboards
|
|
||||||
3. Focus on Celery task monitoring and operational metrics
|
|
||||||
|
|
||||||
### Short Term (Next 2 Weeks):
|
|
||||||
1. Add bulk operations to Tasks, Content, Keywords admins
|
|
||||||
2. Implement export functionality
|
|
||||||
3. Add advanced Unfold filters (date range, numeric range)
|
|
||||||
|
|
||||||
### Medium Term (Next Month):
|
|
||||||
1. Implement Phase 3: Dashboard and monitoring
|
|
||||||
2. Add Celery task monitoring
|
|
||||||
3. Create operational dashboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Technical Notes
|
|
||||||
|
|
||||||
- **No styling work required** - Unfold provides everything
|
|
||||||
- **Use Unfold classes** - badge, alert, card classes available
|
|
||||||
- **No emoji icons needed** - Unfold has Material Design icons
|
|
||||||
- **Focus on functionality** - UI is already handled
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
- **Unfold Documentation:** https://unfoldadmin.com/
|
|
||||||
- **Current Admin:** https://api.igny8.com/admin/
|
|
||||||
- **Implementation Plan:** `/data/app/igny8/DJANGO-ADMIN-IMPROVEMENT-PLAN.md`
|
|
||||||
@@ -46,17 +46,11 @@ This caused style conflicts, crashes, and inconsistent UI.
|
|||||||
- Unfold apps MUST be before `django.contrib.admin`
|
- Unfold apps MUST be before `django.contrib.admin`
|
||||||
- Configured properly in settings.py
|
- Configured properly in settings.py
|
||||||
|
|
||||||
7. **UserAdmin Popup Styling** - User edit form in popup used default Django styling
|
|
||||||
- Changed `UserAdmin` to inherit from both `BaseUserAdmin` and `ModelAdmin`
|
|
||||||
- Multiple inheritance preserves Django user functionality + Unfold styling
|
|
||||||
- Popups now use Unfold templates with modern icons and widgets
|
|
||||||
|
|
||||||
**✅ Result: Single Clean Admin System**
|
**✅ Result: Single Clean Admin System**
|
||||||
- **ONLY Unfold** - No more conflicts
|
- **ONLY Unfold** - No more conflicts
|
||||||
- Modern, responsive UI with Tailwind CSS
|
- Modern, responsive UI with Tailwind CSS
|
||||||
- Dark mode support
|
- Dark mode support
|
||||||
- Advanced filters and bulk operations built-in
|
- Advanced filters and bulk operations built-in
|
||||||
- All popups and forms use Unfold styling
|
|
||||||
- All containers running healthy
|
- All containers running healthy
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -102,21 +96,20 @@ This document outlines a comprehensive improvement plan for the IGNY8 Django Adm
|
|||||||
|
|
||||||
### ✅ Strengths
|
### ✅ Strengths
|
||||||
|
|
||||||
1. **Modern UI Theme** - Unfold provides beautiful, responsive Tailwind-based design with zero custom CSS
|
1. **Modern UI Theme** - Unfold provides beautiful, responsive Tailwind-based design
|
||||||
2. **Consistent Styling** - All admin pages, popups, and forms use Unfold templates
|
2. **Custom Admin Site** - Igny8AdminSite with logical grouping (maintained)
|
||||||
3. **Custom Admin Site** - Igny8AdminSite with logical grouping (maintained)
|
3. **Multi-Tenancy Support** - AccountAdminMixin and SiteSectorAdminMixin
|
||||||
4. **Multi-Tenancy Support** - AccountAdminMixin and SiteSectorAdminMixin
|
4. **Payment Approval Workflow** - Comprehensive payment approval system
|
||||||
5. **Payment Approval Workflow** - Comprehensive payment approval system
|
5. **Custom Actions** - API key generation, payment approval/rejection
|
||||||
6. **Custom Actions** - API key generation, payment approval/rejection
|
6. **Field Customization** - Custom fieldsets and readonly fields
|
||||||
7. **Field Customization** - Custom fieldsets and readonly fields
|
|
||||||
|
|
||||||
### ⚠️ Issues Remaining
|
### ⚠️ Issues Remaining
|
||||||
|
|
||||||
#### 1. **Sidebar Menu Organization**
|
#### 1. **Sidebar Menu Organization**
|
||||||
- ✅ Current get_app_list() structure works
|
- ✅ Current get_app_list() structure works but can be enhanced with Unfold features
|
||||||
- Missing PlanLimitUsage model (needs to be added to admin)
|
- Need to add icons to models for better visual recognition
|
||||||
- Some empty groups appearing (site_building models don't exist)
|
- Missing PlanLimitUsage model (needs to be added)
|
||||||
- Need to clean up model groupings
|
- Some empty groups appearing
|
||||||
|
|
||||||
#### 2. **Unused/Empty Models** (Same as before)
|
#### 2. **Unused/Empty Models** (Same as before)
|
||||||
- **site_building** models referenced but don't exist
|
- **site_building** models referenced but don't exist
|
||||||
@@ -179,35 +172,19 @@ This document outlines a comprehensive improvement plan for the IGNY8 Django Adm
|
|||||||
|
|
||||||
## Phase 1: Critical Fixes & Model Updates (Week 1)
|
## Phase 1: Critical Fixes & Model Updates (Week 1)
|
||||||
|
|
||||||
### 1.1 Clean Up Sidebar Menu Organization
|
### 1.1 Remove Unused Models from Admin Site
|
||||||
|
|
||||||
**Problem:** site_building models referenced but don't exist, causing confusion. Some empty groups appearing.
|
**Problem:** site_building models referenced but don't exist, causing confusion
|
||||||
|
|
||||||
**Action:**
|
**Action:**
|
||||||
|
- Remove from `backend/igny8_core/admin/site.py` custom_groups:
|
||||||
1. **Remove non-existent site_building models** from `backend/igny8_core/admin/site.py` custom_groups:
|
- BusinessType
|
||||||
- BusinessType
|
- AudienceProfile
|
||||||
- AudienceProfile
|
- BrandPersonality
|
||||||
- BrandPersonality
|
- HeroImageryDirection
|
||||||
- HeroImageryDirection
|
|
||||||
|
|
||||||
2. **Add missing PlanLimitUsage model** to Billing group:
|
|
||||||
```python
|
|
||||||
'Billing & Accounts': {
|
|
||||||
'models': [
|
|
||||||
('igny8_core_auth', 'Plan'),
|
|
||||||
('billing', 'PlanLimitUsage'), # ADD THIS
|
|
||||||
('igny8_core_auth', 'Account'),
|
|
||||||
# ... rest of models
|
|
||||||
],
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Verify all referenced models exist** - check that each model in custom_groups is actually registered
|
|
||||||
|
|
||||||
**Files to modify:**
|
**Files to modify:**
|
||||||
- `/data/app/igny8/backend/igny8_core/admin/site.py`
|
- `/data/app/igny8/backend/igny8_core/admin/site.py`
|
||||||
- Verify PlanLimitUsage is registered in admin
|
|
||||||
|
|
||||||
### 1.2 Resolve Duplicate Model Registrations
|
### 1.2 Resolve Duplicate Model Registrations
|
||||||
|
|
||||||
@@ -258,13 +235,62 @@ class TasksAdmin(SiteSectorAdminMixin, ModelAdmin):
|
|||||||
- `/data/app/igny8/backend/igny8_core/business/integration/admin.py`
|
- `/data/app/igny8/backend/igny8_core/business/integration/admin.py`
|
||||||
- All other admin files
|
- All other admin files
|
||||||
|
|
||||||
### 1.4 Test Admin Configuration
|
### 1.4 Add Model Icons for Visual Navigation
|
||||||
|
|
||||||
**Action:** After cleanup, verify:
|
**Action:** Add icon declarations to each admin class using Unfold's icon system (Material Symbols):
|
||||||
- All sidebar groups display correctly
|
|
||||||
- No 404 errors when clicking model links
|
```python
|
||||||
- All registered models appear in appropriate groups
|
class AccountAdmin(AccountAdminMixin, ModelAdmin):
|
||||||
- No empty groups in sidebar
|
# Add icon for sidebar
|
||||||
|
icon = "business" # Material symbol name
|
||||||
|
|
||||||
|
class ContentAdmin(SiteSectorAdminMixin, ModelAdmin):
|
||||||
|
icon = "article"
|
||||||
|
|
||||||
|
class TasksAdmin(SiteSectorAdminMixin, ModelAdmin):
|
||||||
|
icon = "task"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Icon Mapping:**
|
||||||
|
|
||||||
|
| Model | Icon | Material Symbol |
|
||||||
|
|-------|------|----------------|
|
||||||
|
| Account | business | Business/company icon |
|
||||||
|
| Plan | card_membership | Membership card |
|
||||||
|
| Site | language | Globe/website icon |
|
||||||
|
| User | person | Person icon |
|
||||||
|
| Content | article | Article/document |
|
||||||
|
| Tasks | task | Checkbox list |
|
||||||
|
| Clusters | bubble_chart | Cluster diagram |
|
||||||
|
| Keywords | vpn_key | Key icon |
|
||||||
|
| Payment | payment | Payment icon |
|
||||||
|
| Invoice | receipt | Receipt icon |
|
||||||
|
| Automation | settings_suggest | Automation gear |
|
||||||
|
| Integration | integration_instructions | Integration icon |
|
||||||
|
|
||||||
|
### 1.5 Configure Unfold Colors and Branding
|
||||||
|
|
||||||
|
**Already Done:** Basic UNFOLD configuration in settings.py
|
||||||
|
|
||||||
|
**Additional Customization:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# In settings.py UNFOLD dict
|
||||||
|
"SITE_FAVICONS": [
|
||||||
|
{
|
||||||
|
"rel": "icon",
|
||||||
|
"sizes": "32x32",
|
||||||
|
"type": "image/png",
|
||||||
|
"href": lambda request: static("favicons/favicon-32x32.png"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"SIDEBAR": {
|
||||||
|
"show_search": True,
|
||||||
|
"show_all_applications": True,
|
||||||
|
"navigation": None, # Use get_app_list() from Igny8AdminSite
|
||||||
|
},
|
||||||
|
"THEME": "light", # or "dark" or "auto"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -592,22 +618,23 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>IGNY8 Admin Dashboard</h1>
|
<h1>IGNY8 Admin Dashboard</h1>
|
||||||
|
|
||||||
<!-- Unfold will automatically style these using its Tailwind-based theme -->
|
|
||||||
<div class="dashboard-grid">
|
<div class="dashboard-grid">
|
||||||
<!-- Accounts Overview -->
|
<!-- Accounts Overview -->
|
||||||
<div class="dashboard-card">
|
<div class="dashboard-card">
|
||||||
<h2>Accounts</h2>
|
<h2>👥 Accounts</h2>
|
||||||
<div class="metric-row">
|
<div class="metric-row">
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ accounts.total }}</span>
|
<span class="metric-value">{{ accounts.total }}</span>
|
||||||
<span class="metric-label">Total Accounts</span>
|
<span class="metric-label">Total Accounts</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ accounts.active }}</span>
|
<span class="metric-value status-active">{{ accounts.active }}</span>
|
||||||
<span class="metric-label">Active</span>
|
<span class="metric-label">Active</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ accounts.low_credit }}</span>
|
<span class="metric-value {% if accounts.low_credit > 0 %}credits-low{% endif %}">
|
||||||
|
{{ accounts.low_credit }}
|
||||||
|
</span>
|
||||||
<span class="metric-label">Low Credits (< 100)</span>
|
<span class="metric-label">Low Credits (< 100)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -615,7 +642,7 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
|
|
||||||
<!-- Content Production -->
|
<!-- Content Production -->
|
||||||
<div class="dashboard-card">
|
<div class="dashboard-card">
|
||||||
<h2>Content Production</h2>
|
<h2>📝 Content Production</h2>
|
||||||
<div class="metric-row">
|
<div class="metric-row">
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ content.this_week }}</span>
|
<span class="metric-value">{{ content.this_week }}</span>
|
||||||
@@ -626,7 +653,7 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
<span class="metric-label">This Month</span>
|
<span class="metric-label">This Month</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ content.tasks_pending }}</span>
|
<span class="metric-value status-pending">{{ content.tasks_pending }}</span>
|
||||||
<span class="metric-label">Tasks Pending</span>
|
<span class="metric-label">Tasks Pending</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -634,13 +661,15 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
|
|
||||||
<!-- Billing Overview -->
|
<!-- Billing Overview -->
|
||||||
<div class="dashboard-card">
|
<div class="dashboard-card">
|
||||||
<h2>Billing</h2>
|
<h2>💰 Billing</h2>
|
||||||
<div class="metric-row">
|
<div class="metric-row">
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ billing.pending_payments }}</span>
|
<span class="metric-value {% if billing.pending_payments > 0 %}status-pending{% endif %}">
|
||||||
|
{{ billing.pending_payments }}
|
||||||
|
</span>
|
||||||
<span class="metric-label">Pending Approvals</span>
|
<span class="metric-label">Pending Approvals</span>
|
||||||
<a href="{% url 'admin:billing_payment_changelist' %}?status=pending_approval">
|
<a href="{% url 'admin:billing_payment_changelist' %}?status=pending_approval" class="metric-link">
|
||||||
Review
|
Review →
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
@@ -656,18 +685,20 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
|
|
||||||
<!-- Automation Status -->
|
<!-- Automation Status -->
|
||||||
<div class="dashboard-card">
|
<div class="dashboard-card">
|
||||||
<h2>Automation</h2>
|
<h2>🤖 Automation</h2>
|
||||||
<div class="metric-row">
|
<div class="metric-row">
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ automation.running }}</span>
|
<span class="metric-value status-active">{{ automation.running }}</span>
|
||||||
<span class="metric-label">Running Now</span>
|
<span class="metric-label">Running Now</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ automation.failed_this_week }}</span>
|
<span class="metric-value {% if automation.failed_this_week > 0 %}status-inactive{% endif %}">
|
||||||
|
{{ automation.failed_this_week }}
|
||||||
|
</span>
|
||||||
<span class="metric-label">Failed (7 days)</span>
|
<span class="metric-label">Failed (7 days)</span>
|
||||||
{% if automation.failed_this_week > 0 %}
|
{% if automation.failed_this_week > 0 %}
|
||||||
<a href="{% url 'admin:automation_automationrun_changelist' %}?status=failed">
|
<a href="{% url 'admin:automation_automationrun_changelist' %}?status=failed" class="metric-link">
|
||||||
Review
|
Review →
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@@ -676,25 +707,84 @@ File: `backend/igny8_core/templates/admin/dashboard.html`
|
|||||||
|
|
||||||
<!-- Integration Health -->
|
<!-- Integration Health -->
|
||||||
<div class="dashboard-card">
|
<div class="dashboard-card">
|
||||||
<h2>Integration Health</h2>
|
<h2>🔗 Integration Health</h2>
|
||||||
<div class="metric-row">
|
<div class="metric-row">
|
||||||
<div class="metric">
|
<div class="metric">
|
||||||
<span class="metric-value">{{ integration.sync_failed_today }}</span>
|
<span class="metric-value {% if integration.sync_failed_today > 0 %}status-inactive{% endif %}">
|
||||||
|
{{ integration.sync_failed_today }}
|
||||||
|
</span>
|
||||||
<span class="metric-label">Failed Syncs Today</span>
|
<span class="metric-label">Failed Syncs Today</span>
|
||||||
{% if integration.sync_failed_today > 0 %}
|
{% if integration.sync_failed_today > 0 %}
|
||||||
<a href="{% url 'admin:integration_syncevent_changelist' %}?success=False">
|
<a href="{% url 'admin:integration_syncevent_changelist' %}?success=False" class="metric-link">
|
||||||
Review
|
Review →
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dashboard-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-card {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-card h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
border-bottom: 2px solid #417690;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #417690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-link {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #417690;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Unfold automatically provides styling via Tailwind CSS. No custom CSS needed - use Unfold's utility classes if customization is required.
|
|
||||||
|
|
||||||
**Update admin site URLs:**
|
**Update admin site URLs:**
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -790,17 +880,10 @@ class AccountAdmin(AccountAdminMixin, admin.ModelAdmin):
|
|||||||
|
|
||||||
issue_text = ', '.join(issues) if issues else 'Healthy'
|
issue_text = ', '.join(issues) if issues else 'Healthy'
|
||||||
|
|
||||||
# Use Unfold badge classes instead of inline styles
|
|
||||||
if score >= 80:
|
|
||||||
badge_class = 'success'
|
|
||||||
elif score >= 60:
|
|
||||||
badge_class = 'warning'
|
|
||||||
else:
|
|
||||||
badge_class = 'danger'
|
|
||||||
|
|
||||||
return format_html(
|
return format_html(
|
||||||
'<span class="badge badge-{}">{}</span>',
|
'<span style="color: {}; font-size: 18px;">{}</span> '
|
||||||
badge_class, issue_text
|
'<span style="color: {};">{}</span>',
|
||||||
|
color, icon, color, issue_text
|
||||||
)
|
)
|
||||||
health_indicator.short_description = 'Health'
|
health_indicator.short_description = 'Health'
|
||||||
```
|
```
|
||||||
@@ -889,6 +972,11 @@ class AdminAlerts:
|
|||||||
<div class="alerts-section">
|
<div class="alerts-section">
|
||||||
{% for alert in alerts %}
|
{% for alert in alerts %}
|
||||||
<div class="alert alert-{{ alert.level }}">
|
<div class="alert alert-{{ alert.level }}">
|
||||||
|
<span class="alert-icon">
|
||||||
|
{% if alert.level == 'error' %}🔴{% endif %}
|
||||||
|
{% if alert.level == 'warning' %}⚠️{% endif %}
|
||||||
|
{% if alert.level == 'info' %}ℹ️{% endif %}
|
||||||
|
</span>
|
||||||
<span class="alert-message">{{ alert.message }}</span>
|
<span class="alert-message">{{ alert.message }}</span>
|
||||||
<a href="{{ alert.url }}" class="alert-action">{{ alert.action }}</a>
|
<a href="{{ alert.url }}" class="alert-action">{{ alert.action }}</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -897,8 +985,6 @@ class AdminAlerts:
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Use Unfold's alert styling classes. No custom CSS or emoji icons needed.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 4: Analytics & Reporting (Week 7-8)
|
## Phase 4: Analytics & Reporting (Week 7-8)
|
||||||
@@ -1240,25 +1326,20 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
## Implementation Checklist
|
## Implementation Checklist
|
||||||
|
|
||||||
### ✅ Phase 0: Foundation (COMPLETED - Dec 14, 2025)
|
### Week 1-2: Critical Fixes & UI Foundation
|
||||||
|
|
||||||
- [x] Install and configure Unfold theme
|
|
||||||
- [x] Fix all admin classes to inherit from Unfold ModelAdmin
|
|
||||||
- [x] Fix UserAdmin popup styling (multiple inheritance)
|
|
||||||
- [x] Configure UNFOLD settings in settings.py
|
|
||||||
- [x] Update middleware and INSTALLED_APPS
|
|
||||||
- [x] Test all containers running
|
|
||||||
|
|
||||||
### Phase 1: Configuration Cleanup (Week 1) - IN PROGRESS
|
|
||||||
|
|
||||||
- [x] Fix UserAdmin popup styling
|
|
||||||
- [ ] Remove unused site_building models from admin site config
|
- [ ] Remove unused site_building models from admin site config
|
||||||
- [ ] Remove duplicate model registrations (keep modules/ versions)
|
- [ ] Remove duplicate model registrations (keep modules/ versions)
|
||||||
|
- [ ] Reorganize sidebar menu with emoji icons and logical groups
|
||||||
- [ ] Add PlanLimitUsage to Billing & Accounts group
|
- [ ] Add PlanLimitUsage to Billing & Accounts group
|
||||||
- [ ] Verify all model links work
|
- [ ] Install django-admin-interface or django-grappelli
|
||||||
- [ ] Test admin configuration
|
- [ ] Configure admin theme package
|
||||||
|
- [ ] Create custom CSS file for status colors and basic styling
|
||||||
|
- [ ] Create custom base_site.html template
|
||||||
|
- [ ] Test admin UI improvements
|
||||||
|
- [ ] Document theme customization options
|
||||||
|
|
||||||
### Phase 2: Bulk Operations & Export (Week 2-3) - NOT STARTED
|
### Week 3-4: Operational Features
|
||||||
|
|
||||||
- [ ] Add bulk status update actions to Tasks admin
|
- [ ] Add bulk status update actions to Tasks admin
|
||||||
- [ ] Add bulk operations to Content admin
|
- [ ] Add bulk operations to Content admin
|
||||||
@@ -1273,7 +1354,7 @@ class Command(BaseCommand):
|
|||||||
- [ ] Test all bulk operations
|
- [ ] Test all bulk operations
|
||||||
- [ ] Test export functionality
|
- [ ] Test export functionality
|
||||||
|
|
||||||
### Phase 3: Monitoring & Dashboards (Week 4-5) - NOT STARTED
|
### Week 5-6: Monitoring & Dashboards
|
||||||
|
|
||||||
- [ ] Install django-celery-results
|
- [ ] Install django-celery-results
|
||||||
- [ ] Configure Celery to use django-db backend
|
- [ ] Configure Celery to use django-db backend
|
||||||
@@ -1290,7 +1371,7 @@ class Command(BaseCommand):
|
|||||||
- [ ] Test dashboard metrics accuracy
|
- [ ] Test dashboard metrics accuracy
|
||||||
- [ ] Test alert system functionality
|
- [ ] Test alert system functionality
|
||||||
|
|
||||||
### Phase 4: Analytics & Reporting (Week 6-7) - NOT STARTED
|
### Week 7-8: Analytics & Reporting
|
||||||
|
|
||||||
- [ ] Create reports.py module
|
- [ ] Create reports.py module
|
||||||
- [ ] Implement revenue_report view
|
- [ ] Implement revenue_report view
|
||||||
@@ -1304,7 +1385,7 @@ class Command(BaseCommand):
|
|||||||
- [ ] Test all reports with real data
|
- [ ] Test all reports with real data
|
||||||
- [ ] Optimize report queries for performance
|
- [ ] Optimize report queries for performance
|
||||||
|
|
||||||
### Phase 5: Advanced Features (Week 8+) - NOT STARTED
|
### Week 9-10: Advanced Features
|
||||||
|
|
||||||
- [ ] Enable list_editable for Tasks and Keywords
|
- [ ] Enable list_editable for Tasks and Keywords
|
||||||
- [ ] Install django-simple-history
|
- [ ] Install django-simple-history
|
||||||
@@ -1326,38 +1407,40 @@ class Command(BaseCommand):
|
|||||||
### Python Packages
|
### Python Packages
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
# Already installed:
|
# Add to requirements.txt
|
||||||
django-unfold==0.73.1 # Modern admin theme (✅ INSTALLED)
|
django-admin-interface==0.26.0 # Modern admin theme
|
||||||
django-import-export==3.3.1 # CSV/Excel import/export (✅ INSTALLED)
|
django-import-export==3.3.1 # CSV/Excel import/export
|
||||||
django-celery-results==2.5.1 # Celery monitoring (✅ INSTALLED)
|
django-admin-rangefilter==0.11.1 # Date range filters
|
||||||
django-simple-history==3.4.0 # Audit trail (✅ INSTALLED)
|
django-advanced-filters==2.4.0 # Saved filters
|
||||||
|
django-celery-results==2.5.1 # Celery monitoring
|
||||||
# No additional packages needed for styling - Unfold handles everything
|
django-simple-history==3.4.0 # Audit trail
|
||||||
```
|
```
|
||||||
|
|
||||||
### Settings Configuration
|
### Settings Configuration
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# backend/igny8_core/settings.py
|
# backend/igny8_core/settings.py
|
||||||
# ✅ Already configured properly
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'unfold', # ✅ Already installed - Must be before django.contrib.admin
|
'admin_interface', # Must be before django.contrib.admin
|
||||||
'unfold.contrib.filters', # ✅ Already installed
|
'colorfield', # Required by admin_interface
|
||||||
'unfold.contrib.import_export', # ✅ Already installed
|
|
||||||
'unfold.contrib.simple_history', # ✅ Already installed
|
|
||||||
'igny8_core.admin.apps.Igny8AdminConfig',
|
'igny8_core.admin.apps.Igny8AdminConfig',
|
||||||
# ... rest of apps
|
# ... rest of apps
|
||||||
'import_export', # ✅ Already installed
|
'import_export',
|
||||||
'django_celery_results', # ✅ Already installed
|
'rangefilter',
|
||||||
'simple_history', # ✅ Already installed
|
'advanced_filters',
|
||||||
|
'django_celery_results',
|
||||||
|
'simple_history',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Celery Results - ✅ Already configured
|
# Admin Interface Configuration
|
||||||
|
X_FRAME_OPTIONS = 'SAMEORIGIN' # Required for admin_interface
|
||||||
|
|
||||||
|
# Celery Results
|
||||||
CELERY_RESULT_BACKEND = 'django-db'
|
CELERY_RESULT_BACKEND = 'django-db'
|
||||||
CELERY_CACHE_BACKEND = 'django-cache'
|
CELERY_CACHE_BACKEND = 'django-cache'
|
||||||
|
|
||||||
# History Middleware - ✅ Already configured
|
# History Middleware
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
# ... existing middleware
|
# ... existing middleware
|
||||||
'simple_history.middleware.HistoryRequestMiddleware',
|
'simple_history.middleware.HistoryRequestMiddleware',
|
||||||
@@ -1365,19 +1448,31 @@ MIDDLEWARE = [
|
|||||||
|
|
||||||
# Import/Export Settings
|
# Import/Export Settings
|
||||||
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
||||||
|
|
||||||
# UNFOLD configuration - ✅ Already configured in settings.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Database Migrations
|
### Database Migrations
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Already completed - no additional migrations needed for Unfold
|
# After adding packages
|
||||||
# Unfold uses Django's existing admin tables
|
python manage.py migrate admin_interface
|
||||||
|
python manage.py migrate django_celery_results
|
||||||
|
python manage.py migrate simple_history
|
||||||
|
|
||||||
# For future features:
|
# Collect static files
|
||||||
# python manage.py migrate django_celery_results # When adding Celery monitoring
|
python manage.py collectstatic --noinput
|
||||||
# python manage.py migrate simple_history # When adding history to models
|
```
|
||||||
|
|
||||||
|
### Static Files Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/igny8_core/static/
|
||||||
|
├── admin/
|
||||||
|
│ ├── css/
|
||||||
|
│ │ └── igny8_admin.css
|
||||||
|
│ └── js/
|
||||||
|
│ └── igny8_admin.js
|
||||||
|
└── charts/
|
||||||
|
└── chart.min.js
|
||||||
```
|
```
|
||||||
|
|
||||||
### Template Structure
|
### Template Structure
|
||||||
@@ -1431,10 +1526,12 @@ backend/igny8_core/templates/
|
|||||||
|
|
||||||
If issues arise during implementation:
|
If issues arise during implementation:
|
||||||
|
|
||||||
1. **Unfold Issues (unlikely):** Already stable and working
|
1. **Theme Issues:** Revert to default Django admin
|
||||||
- Unfold is well-tested and production-ready
|
```bash
|
||||||
- No custom styling to break
|
# Remove from INSTALLED_APPS
|
||||||
- All standard Django admin features work
|
# 'admin_interface',
|
||||||
|
python manage.py migrate admin_interface zero
|
||||||
|
```
|
||||||
|
|
||||||
2. **Duplicate Registration Issues:**
|
2. **Duplicate Registration Issues:**
|
||||||
- Keep `modules/` admin files active
|
- Keep `modules/` admin files active
|
||||||
@@ -1536,7 +1633,7 @@ Keep these docs updated:
|
|||||||
|
|
||||||
This comprehensive plan transforms the Django admin from a basic management tool into a powerful operational hub. The phased approach ensures steady progress while minimizing disruption. Focus on Phases 1-3 for immediate operational impact, then expand to analytics and advanced features in Phases 4-5.
|
This comprehensive plan transforms the Django admin from a basic management tool into a powerful operational hub. The phased approach ensures steady progress while minimizing disruption. Focus on Phases 1-3 for immediate operational impact, then expand to analytics and advanced features in Phases 4-5.
|
||||||
|
|
||||||
**Estimated Total Effort:** 2-4 weeks with 1-2 developers (reduced since styling is already complete via Unfold)
|
**Estimated Total Effort:** 4-6 weeks with 1-2 developers
|
||||||
|
|
||||||
**Priority:** 🔴 High - Critical for efficient operations at scale
|
**Priority:** 🔴 High - Critical for efficient operations at scale
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from igny8_core.business.billing.models import (
|
|||||||
Payment,
|
Payment,
|
||||||
CreditPackage,
|
CreditPackage,
|
||||||
PaymentMethodConfig,
|
PaymentMethodConfig,
|
||||||
PlanLimitUsage,
|
|
||||||
)
|
)
|
||||||
from .models import CreditTransaction, CreditUsageLog, AccountPaymentMethod
|
from .models import CreditTransaction, CreditUsageLog, AccountPaymentMethod
|
||||||
from import_export.admin import ExportMixin
|
from import_export.admin import ExportMixin
|
||||||
@@ -494,46 +493,3 @@ class CreditCostConfigAdmin(ModelAdmin):
|
|||||||
obj.updated_by = request.user
|
obj.updated_by = request.user
|
||||||
super().save_model(request, obj, form, change)
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(PlanLimitUsage)
|
|
||||||
class PlanLimitUsageAdmin(AccountAdminMixin, ModelAdmin):
|
|
||||||
"""Admin for tracking plan limit usage across billing periods"""
|
|
||||||
list_display = [
|
|
||||||
'account',
|
|
||||||
'limit_type',
|
|
||||||
'amount_used',
|
|
||||||
'period_display',
|
|
||||||
'created_at',
|
|
||||||
]
|
|
||||||
list_filter = [
|
|
||||||
'limit_type',
|
|
||||||
('period_start', DateRangeFilter),
|
|
||||||
('period_end', DateRangeFilter),
|
|
||||||
'account',
|
|
||||||
]
|
|
||||||
search_fields = ['account__name']
|
|
||||||
readonly_fields = ['created_at', 'updated_at']
|
|
||||||
date_hierarchy = 'period_start'
|
|
||||||
|
|
||||||
fieldsets = (
|
|
||||||
('Usage Info', {
|
|
||||||
'fields': ('account', 'limit_type', 'amount_used')
|
|
||||||
}),
|
|
||||||
('Billing Period', {
|
|
||||||
'fields': ('period_start', 'period_end')
|
|
||||||
}),
|
|
||||||
('Metadata', {
|
|
||||||
'fields': ('metadata',),
|
|
||||||
'classes': ('collapse',)
|
|
||||||
}),
|
|
||||||
('Timestamps', {
|
|
||||||
'fields': ('created_at', 'updated_at'),
|
|
||||||
'classes': ('collapse',)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
def period_display(self, obj):
|
|
||||||
"""Display billing period range"""
|
|
||||||
return f"{obj.period_start} to {obj.period_end}"
|
|
||||||
period_display.short_description = 'Billing Period'
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from unfold.admin import ModelAdmin
|
from unfold.admin import ModelAdmin
|
||||||
from unfold.contrib.filters.admin import (
|
|
||||||
RangeDateFilter,
|
|
||||||
RangeNumericFilter,
|
|
||||||
RelatedDropdownFilter,
|
|
||||||
ChoicesDropdownFilter,
|
|
||||||
)
|
|
||||||
from igny8_core.admin.base import SiteSectorAdminMixin
|
from igny8_core.admin.base import SiteSectorAdminMixin
|
||||||
from .models import Keywords, Clusters, ContentIdeas
|
from .models import Keywords, Clusters, ContentIdeas
|
||||||
from import_export.admin import ExportMixin
|
from import_export.admin import ExportMixin
|
||||||
@@ -25,13 +19,7 @@ class KeywordsResource(resources.ModelResource):
|
|||||||
@admin.register(Clusters)
|
@admin.register(Clusters)
|
||||||
class ClustersAdmin(SiteSectorAdminMixin, ModelAdmin):
|
class ClustersAdmin(SiteSectorAdminMixin, ModelAdmin):
|
||||||
list_display = ['name', 'site', 'sector', 'keywords_count', 'volume', 'status', 'created_at']
|
list_display = ['name', 'site', 'sector', 'keywords_count', 'volume', 'status', 'created_at']
|
||||||
list_filter = [
|
list_filter = ['status', 'site', 'sector']
|
||||||
('status', ChoicesDropdownFilter),
|
|
||||||
('site', RelatedDropdownFilter),
|
|
||||||
('sector', RelatedDropdownFilter),
|
|
||||||
('volume', RangeNumericFilter),
|
|
||||||
('created_at', RangeDateFilter),
|
|
||||||
]
|
|
||||||
search_fields = ['name']
|
search_fields = ['name']
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
autocomplete_fields = ['site', 'sector']
|
autocomplete_fields = ['site', 'sector']
|
||||||
@@ -56,17 +44,8 @@ class ClustersAdmin(SiteSectorAdminMixin, ModelAdmin):
|
|||||||
class KeywordsAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
class KeywordsAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
||||||
resource_class = KeywordsResource
|
resource_class = KeywordsResource
|
||||||
list_display = ['keyword', 'seed_keyword', 'site', 'sector', 'cluster', 'volume', 'difficulty', 'intent', 'status', 'created_at']
|
list_display = ['keyword', 'seed_keyword', 'site', 'sector', 'cluster', 'volume', 'difficulty', 'intent', 'status', 'created_at']
|
||||||
list_filter = [
|
list_filter = ['status', 'seed_keyword__intent', 'site', 'sector', 'seed_keyword__industry', 'seed_keyword__sector']
|
||||||
('status', ChoicesDropdownFilter),
|
search_fields = ['seed_keyword__keyword']
|
||||||
('intent', ChoicesDropdownFilter),
|
|
||||||
('site', RelatedDropdownFilter),
|
|
||||||
('sector', RelatedDropdownFilter),
|
|
||||||
('cluster', RelatedDropdownFilter),
|
|
||||||
('volume', RangeNumericFilter),
|
|
||||||
('difficulty', RangeNumericFilter),
|
|
||||||
('created_at', RangeDateFilter),
|
|
||||||
]
|
|
||||||
search_fields = ['keyword', 'seed_keyword__keyword']
|
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
autocomplete_fields = ['cluster', 'site', 'sector', 'seed_keyword']
|
autocomplete_fields = ['cluster', 'site', 'sector', 'seed_keyword']
|
||||||
actions = [
|
actions = [
|
||||||
@@ -154,16 +133,7 @@ class KeywordsAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
|||||||
@admin.register(ContentIdeas)
|
@admin.register(ContentIdeas)
|
||||||
class ContentIdeasAdmin(SiteSectorAdminMixin, ModelAdmin):
|
class ContentIdeasAdmin(SiteSectorAdminMixin, ModelAdmin):
|
||||||
list_display = ['idea_title', 'site', 'sector', 'description_preview', 'content_type', 'content_structure', 'status', 'keyword_cluster', 'estimated_word_count', 'created_at']
|
list_display = ['idea_title', 'site', 'sector', 'description_preview', 'content_type', 'content_structure', 'status', 'keyword_cluster', 'estimated_word_count', 'created_at']
|
||||||
list_filter = [
|
list_filter = ['status', 'content_type', 'content_structure', 'site', 'sector']
|
||||||
('status', ChoicesDropdownFilter),
|
|
||||||
('content_type', ChoicesDropdownFilter),
|
|
||||||
('content_structure', ChoicesDropdownFilter),
|
|
||||||
('site', RelatedDropdownFilter),
|
|
||||||
('sector', RelatedDropdownFilter),
|
|
||||||
('keyword_cluster', RelatedDropdownFilter),
|
|
||||||
('estimated_word_count', RangeNumericFilter),
|
|
||||||
('created_at', RangeDateFilter),
|
|
||||||
]
|
|
||||||
search_fields = ['idea_title', 'target_keywords', 'description']
|
search_fields = ['idea_title', 'target_keywords', 'description']
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
readonly_fields = ['created_at', 'updated_at']
|
readonly_fields = ['created_at', 'updated_at']
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from unfold.admin import ModelAdmin, TabularInline
|
from unfold.admin import ModelAdmin, TabularInline
|
||||||
from unfold.contrib.filters.admin import (
|
|
||||||
RangeDateFilter,
|
|
||||||
RangeNumericFilter,
|
|
||||||
RelatedDropdownFilter,
|
|
||||||
ChoicesDropdownFilter,
|
|
||||||
)
|
|
||||||
from igny8_core.admin.base import SiteSectorAdminMixin
|
from igny8_core.admin.base import SiteSectorAdminMixin
|
||||||
from .models import Tasks, Images, Content
|
from .models import Tasks, Images, Content
|
||||||
from igny8_core.business.content.models import ContentTaxonomy, ContentAttribute, ContentTaxonomyRelation, ContentClusterMap
|
from igny8_core.business.content.models import ContentTaxonomy, ContentAttribute, ContentTaxonomyRelation, ContentClusterMap
|
||||||
@@ -36,15 +30,7 @@ class TaskResource(resources.ModelResource):
|
|||||||
class TasksAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
class TasksAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
||||||
resource_class = TaskResource
|
resource_class = TaskResource
|
||||||
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'status', 'cluster', 'created_at']
|
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'status', 'cluster', 'created_at']
|
||||||
list_filter = [
|
list_filter = ['status', 'content_type', 'content_structure', 'site', 'sector', 'cluster']
|
||||||
('status', ChoicesDropdownFilter),
|
|
||||||
('content_type', ChoicesDropdownFilter),
|
|
||||||
('content_structure', ChoicesDropdownFilter),
|
|
||||||
('site', RelatedDropdownFilter),
|
|
||||||
('sector', RelatedDropdownFilter),
|
|
||||||
('cluster', RelatedDropdownFilter),
|
|
||||||
('created_at', RangeDateFilter),
|
|
||||||
]
|
|
||||||
search_fields = ['title', 'description']
|
search_fields = ['title', 'description']
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
readonly_fields = ['created_at', 'updated_at']
|
readonly_fields = ['created_at', 'updated_at']
|
||||||
@@ -200,19 +186,9 @@ class ContentResource(resources.ModelResource):
|
|||||||
@admin.register(Content)
|
@admin.register(Content)
|
||||||
class ContentAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
class ContentAdmin(ExportMixin, SiteSectorAdminMixin, ModelAdmin):
|
||||||
resource_class = ContentResource
|
resource_class = ContentResource
|
||||||
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'source', 'status', 'word_count', 'get_taxonomy_count', 'created_at']
|
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'source', 'status', 'get_taxonomy_count', 'created_at']
|
||||||
list_filter = [
|
list_filter = ['content_type', 'content_structure', 'source', 'status', 'site', 'sector', 'created_at']
|
||||||
('status', ChoicesDropdownFilter),
|
search_fields = ['title', 'content_html', 'external_url']
|
||||||
('content_type', ChoicesDropdownFilter),
|
|
||||||
('content_structure', ChoicesDropdownFilter),
|
|
||||||
('source', ChoicesDropdownFilter),
|
|
||||||
('site', RelatedDropdownFilter),
|
|
||||||
('sector', RelatedDropdownFilter),
|
|
||||||
('cluster', RelatedDropdownFilter),
|
|
||||||
('word_count', RangeNumericFilter),
|
|
||||||
('created_at', RangeDateFilter),
|
|
||||||
]
|
|
||||||
search_fields = ['title', 'content_html', 'external_url', 'meta_title', 'primary_keyword']
|
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
readonly_fields = ['created_at', 'updated_at', 'word_count', 'get_tags_display', 'get_categories_display']
|
readonly_fields = ['created_at', 'updated_at', 'word_count', 'get_tags_display', 'get_categories_display']
|
||||||
autocomplete_fields = ['cluster', 'site', 'sector']
|
autocomplete_fields = ['cluster', 'site', 'sector']
|
||||||
|
|||||||
Reference in New Issue
Block a user