lamost fully fixed umfold template

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-14 17:30:10 +00:00
parent cd2c84116b
commit a6fab8784d
18 changed files with 60 additions and 2125 deletions

View File

@@ -1,70 +1,11 @@
{% extends "admin/base.html" %}
{% load static %}
{% block title %}{{ title }} | IGNY8 Admin{% endblock %}
{% block extrahead %}
{{ block.super }}
<!-- FontAwesome Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
{% endblock %}
{% block branding %}
<h1 id="site-name">
<a href="{% url 'admin:index' %}">
<i class="fas fa-rocket"></i> IGNY8 Administration
🚀 IGNY8 Administration
</a>
</h1>
{% endblock %}
{% block userlinks %}
<a href="{% url 'admin:dashboard' %}" class="dashboard-link">
<i class="fas fa-chart-line"></i>
<span>Dashboard</span>
</a>
{{ block.super }}
{% endblock %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'admin/css/igny8_admin.css' %}">
<style>
/* Dashboard link in header */
.dashboard-link {
display: inline-flex !important;
align-items: center !important;
gap: 8px !important;
padding: 10px 20px !important;
margin-right: 20px !important;
background: rgba(255, 255, 255, 0.15) !important;
color: white !important;
text-decoration: none !important;
border-radius: 8px !important;
font-weight: 600 !important;
font-size: 14px !important;
transition: all 0.2s ease !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
}
.dashboard-link:hover {
background: rgba(255, 255, 255, 0.25) !important;
transform: translateY(-1px) !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15) !important;
}
.dashboard-link i {
font-size: 16px !important;
}
/* User tools spacing */
#user-tools {
display: flex !important;
align-items: center !important;
gap: 15px !important;
padding: 10px 20px !important;
}
</style>
{% endblock %}
{% block nav-global %}{% endblock %}

View File

@@ -1,75 +0,0 @@
{% extends "admin/base_site.html" %}
{% load static %}
{% block content %}
<h1>{{ title }}</h1>
<form method="post">
{% csrf_token %}
<div class="form-group" style="margin: 20px 0;">
{{ form.as_p }}
</div>
<div class="submit-row" style="margin-top: 20px;">
<input type="hidden" name="action" value="{{ action }}">
<input type="hidden" name="_selected_action" value="{{ queryset|join:',' }}">
<input type="submit" name="apply" value="Apply" class="button" style="margin-right: 10px;">
<a href="javascript:history.back()" class="button">Cancel</a>
</div>
<fieldset class="module aligned" style="margin-top: 20px;">
<h2>Selected Items ({{ queryset.count }})</h2>
<ul style="list-style: none; padding: 10px;">
{% for item in queryset|slice:":10" %}
<li style="padding: 5px 0; border-bottom: 1px solid var(--igny8-stroke);">
{{ item }}
</li>
{% endfor %}
{% if queryset.count > 10 %}
<li style="padding: 10px 0; font-style: italic; color: var(--igny8-text-dim);">
...and {{ queryset.count|add:"-10" }} more
</li>
{% endif %}
</ul>
</fieldset>
</form>
<style>
.form-group label {
font-weight: bold;
display: block;
margin-bottom: 5px;
color: var(--igny8-text);
}
.form-group select,
.form-group input {
padding: 8px;
border: 1px solid var(--igny8-stroke);
border-radius: 4px;
min-width: 300px;
}
.form-group .helptext {
display: block;
margin-top: 5px;
color: var(--igny8-text-dim);
font-size: 12px;
}
.form-group ul {
list-style: none;
padding: 0;
}
.form-group ul li {
padding: 5px 0;
}
.form-group ul li label {
font-weight: normal;
margin-left: 5px;
}
</style>
{% endblock %}

View File

@@ -1,419 +0,0 @@
{% extends "admin/base_site.html" %}
{% load static %}
{% block title %}IGNY8 Dashboard{% endblock %}
{% block extrahead %}
{{ block.super }}
<style>
.dashboard-container {
padding: 20px;
max-width: 1400px;
margin: 0 auto;
}
.dashboard-header {
background: linear-gradient(135deg, #0d1b2a 0%, #1a2e44 100%);
color: white;
padding: 30px;
border-radius: 12px;
margin-bottom: 30px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.dashboard-header-content h1 {
margin: 0 0 10px 0;
font-size: 32px;
font-weight: 600;
}
.dashboard-header-content p {
margin: 0;
opacity: 0.9;
font-size: 14px;
}
.dashboard-nav {
display: flex;
gap: 12px;
}
.dashboard-nav a {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.15);
color: white !important;
text-decoration: none;
border-radius: 6px;
font-weight: 500;
font-size: 14px;
transition: background 0.2s;
backdrop-filter: blur(10px);
}
.dashboard-nav a:hover {
background: rgba(255, 255, 255, 0.25);
}
.alerts-section {
margin-bottom: 30px;
}
.alert-card {
padding: 16px 20px;
border-radius: 8px;
margin-bottom: 12px;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.alert-card.error {
background: #fef2f2;
border-left: 4px solid #ef4444;
}
.alert-card.warning {
background: #fff7ed;
border-left: 4px solid #ff7a00;
}
.alert-card.info {
background: #eff6ff;
border-left: 4px solid #0693e3;
}
.alert-content {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
}
.alert-icon {
font-size: 24px;
}
.alert-message {
font-size: 14px;
font-weight: 500;
color: #1f2937;
}
.alert-action {
padding: 8px 16px;
background: white;
border: 1px solid #d1d5db;
border-radius: 6px;
text-decoration: none;
color: #374151;
font-size: 13px;
font-weight: 500;
transition: all 0.2s;
}
.alert-action:hover {
background: #f9fafb;
border-color: #9ca3af;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.metric-card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
border-top: 4px solid #0693e3;
}
.metric-card h3 {
margin: 0 0 20px 0;
font-size: 16px;
font-weight: 600;
color: #0d1b2a;
display: flex;
align-items: center;
gap: 8px;
}
.metric-card .icon {
font-size: 20px;
}
.metric-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #f3f4f6;
}
.metric-row:last-child {
border-bottom: none;
padding-bottom: 0;
}
.metric-label {
font-size: 14px;
color: #6b7280;
}
.metric-value {
font-size: 18px;
font-weight: 600;
color: #1f2937;
}
.metric-value.success {
color: #0bbf87;
}
.metric-value.warning {
color: #ff7a00;
}
.metric-value.error {
color: #ef4444;
}
.metric-value.info {
color: #0693e3;
}
.quick-actions {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.quick-actions h3 {
margin: 0 0 20px 0;
font-size: 18px;
font-weight: 600;
color: #0d1b2a;
}
.action-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 12px;
}
.action-button {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
padding: 20px 16px;
background: linear-gradient(135deg, #0693e3 0%, #0d82c8 100%);
color: white !important;
text-decoration: none;
border-radius: 8px;
text-align: center;
font-weight: 600;
font-size: 14px;
transition: transform 0.2s, box-shadow 0.2s;
box-shadow: 0 2px 4px rgba(6, 147, 227, 0.2);
min-height: 80px;
}
.action-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(6, 147, 227, 0.3);
color: white !important;
background: linear-gradient(135deg, #0780cb 0%, #0c75b5 100%);
}
.action-button .icon {
font-size: 24px;
}
.action-button .label {
color: white !important;
font-weight: 600;
}
.no-alerts {
text-align: center;
padding: 40px;
color: #6b7280;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.no-alerts .icon {
font-size: 48px;
margin-bottom: 16px;
}
</style>
{% endblock %}
{% block content %}
<div class="dashboard-container">
<div class="dashboard-header">
<div class="dashboard-header-content">
<h1>🚀 IGNY8 Admin Dashboard</h1>
<p>Real-time operational metrics and system health monitoring</p>
</div>
<div class="dashboard-nav">
<a href="/admin/">← Back to Admin</a>
</div>
</div>
{% if alerts %}
<div class="alerts-section">
<h2 style="margin: 0 0 16px 0; font-size: 20px; font-weight: 600;">📢 Active Alerts</h2>
{% for alert in alerts %}
<div class="alert-card {{ alert.level }}">
<div class="alert-content">
<span class="alert-icon">{{ alert.icon }}</span>
<span class="alert-message">{{ alert.message }}</span>
</div>
<a href="{{ alert.url }}" class="alert-action">{{ alert.action }}</a>
</div>
{% endfor %}
</div>
{% else %}
<div class="alerts-section">
<div class="no-alerts">
<div class="icon"></div>
<h3 style="margin: 0 0 8px 0; color: #0bbf87;">All Systems Operational</h3>
<p style="margin: 0;">No active alerts or issues detected</p>
</div>
</div>
{% endif %}
<div class="metrics-grid">
<!-- Accounts Card -->
<div class="metric-card">
<h3><span class="icon">👥</span> Accounts</h3>
<div class="metric-row">
<span class="metric-label">Total Accounts</span>
<span class="metric-value info">{{ accounts.total }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Active Accounts</span>
<span class="metric-value success">{{ accounts.active }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Low Credit Accounts</span>
<span class="metric-value {% if accounts.low_credit > 0 %}warning{% else %}success{% endif %}">{{ accounts.low_credit }}</span>
</div>
</div>
<!-- Content Card -->
<div class="metric-card">
<h3><span class="icon">📚</span> Content</h3>
<div class="metric-row">
<span class="metric-label">Created This Week</span>
<span class="metric-value info">{{ content.this_week }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Created This Month</span>
<span class="metric-value info">{{ content.this_month }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Pending Tasks</span>
<span class="metric-value {% if content.tasks_pending > 50 %}warning{% else %}info{% endif %}">{{ content.tasks_pending }}</span>
</div>
<div class="metric-row">
<span class="metric-label">In Progress</span>
<span class="metric-value info">{{ content.tasks_in_progress }}</span>
</div>
</div>
<!-- Billing Card -->
<div class="metric-card">
<h3><span class="icon">💰</span> Billing</h3>
<div class="metric-row">
<span class="metric-label">Pending Payments</span>
<span class="metric-value {% if billing.pending_payments > 0 %}warning{% else %}success{% endif %}">{{ billing.pending_payments }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Revenue This Month</span>
<span class="metric-value success">${{ billing.payments_this_month|floatformat:2 }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Credits Used This Month</span>
<span class="metric-value info">{{ billing.credit_usage_this_month }}</span>
</div>
</div>
<!-- Automation & Integration Card -->
<div class="metric-card">
<h3><span class="icon">🤖</span> Automation & Sync</h3>
<div class="metric-row">
<span class="metric-label">Automations Running</span>
<span class="metric-value info">{{ automation.running }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Failed This Week</span>
<span class="metric-value {% if automation.failed_this_week > 0 %}error{% else %}success{% endif %}">{{ automation.failed_this_week }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Failed Syncs Today</span>
<span class="metric-value {% if integration.sync_failed_today > 5 %}warning{% elif integration.sync_failed_today > 0 %}info{% else %}success{% endif %}">{{ integration.sync_failed_today }}</span>
</div>
</div>
<!-- Celery Tasks Card -->
<div class="metric-card">
<h3><span class="icon">⚙️</span> Celery Tasks</h3>
<div class="metric-row">
<span class="metric-label">Failed Today</span>
<span class="metric-value {% if celery.failed_today > 0 %}error{% else %}success{% endif %}">{{ celery.failed_today }}</span>
</div>
<div class="metric-row">
<span class="metric-label">Pending Tasks</span>
<span class="metric-value info">{{ celery.pending }}</span>
</div>
</div>
</div>
<div class="quick-actions">
<h3>⚡ Quick Actions</h3>
<div class="action-grid">
<a href="/admin/" class="action-button" style="background: linear-gradient(135deg, #0d1b2a 0%, #1a2e44 100%);">
<span class="icon">🏠</span>
<span class="label">Admin Home</span>
</a>
<a href="/admin/igny8_core_auth/account/" class="action-button">
<span class="icon">👥</span>
<span class="label">Manage Accounts</span>
</a>
<a href="/admin/writer/content/" class="action-button">
<span class="icon">📝</span>
<span class="label">View Content</span>
</a>
<a href="/admin/writer/tasks/" class="action-button">
<span class="icon"></span>
<span class="label">Manage Tasks</span>
</a>
<a href="/admin/billing/payment/" class="action-button">
<span class="icon">💳</span>
<span class="label">Review Payments</span>
</a>
<a href="/admin/automation/automationrun/" class="action-button">
<span class="icon">🤖</span>
<span class="label">View Automations</span>
</a>
<a href="/admin/django_celery_results/taskresult/" class="action-button">
<span class="icon">⚙️</span>
<span class="label">Celery Monitor</span>
</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,72 +0,0 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_urls static %}
{% block object-tools-items %}
<li>
<a href="#" class="addlink" onclick="document.getElementById('csv-import-form').style.display='block'; return false;">
Import from CSV
</a>
</li>
{{ block.super }}
{% endblock %}
{% block content %}
<div id="csv-import-form" style="display:none; background: #f8f8f8; padding: 20px; margin: 20px 0; border: 1px solid #ddd;">
<h2>Import Industries from CSV</h2>
<form method="post" enctype="multipart/form-data" action="{% url 'admin_industry_csv_import' %}" id="csv-upload-form">
{% csrf_token %}
<p>
<label for="csv_file">Select CSV file:</label>
<input type="file" name="csv_file" id="csv_file" accept=".csv" required>
</p>
<p>
<strong>CSV Format:</strong> name, description, is_active<br>
<em>Note: Slug will be auto-generated from name</em><br>
<a href="{% url 'admin_industry_csv_template' %}" download>Download template with examples</a>
</p>
<p>
<button type="submit" class="button">Upload and Import</button>
<button type="button" class="button" onclick="document.getElementById('csv-import-form').style.display='none'">Cancel</button>
</p>
</form>
<div id="import-results"></div>
</div>
<script>
document.getElementById('csv-upload-form').addEventListener('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
var resultsDiv = document.getElementById('import-results');
resultsDiv.innerHTML = '<p>Importing...</p>';
fetch('{% url "admin_industry_csv_import" %}', {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
resultsDiv.innerHTML = '<p style="color: green;">✓ Import successful!<br>' +
'Created: ' + data.created + '<br>' +
'Updated: ' + data.updated + '<br>' +
(data.errors.length > 0 ? 'Errors: ' + data.errors.join('<br>') : '') +
'</p>';
setTimeout(function() {
window.location.reload();
}, 2000);
} else {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + data.error + '</p>';
}
})
.catch(error => {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + error + '</p>';
});
});
</script>
{{ block.super }}
{% endblock %}

View File

@@ -1,72 +0,0 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_urls static %}
{% block object-tools-items %}
<li>
<a href="#" class="addlink" onclick="document.getElementById('csv-import-form').style.display='block'; return false;">
Import from CSV
</a>
</li>
{{ block.super }}
{% endblock %}
{% block content %}
<div id="csv-import-form" style="display:none; background: #f8f8f8; padding: 20px; margin: 20px 0; border: 1px solid #ddd;">
<h2>Import Industry Sectors from CSV</h2>
<form method="post" enctype="multipart/form-data" action="{% url 'admin_industrysector_csv_import' %}" id="csv-upload-form">
{% csrf_token %}
<p>
<label for="csv_file">Select CSV file:</label>
<input type="file" name="csv_file" id="csv_file" accept=".csv" required>
</p>
<p>
<strong>CSV Format:</strong> name, industry, description, is_active<br>
<em>Note: Use industry name (not slug). Slug will be auto-generated from name</em><br>
<a href="{% url 'admin_industrysector_csv_template' %}" download>Download template with examples</a>
</p>
<p>
<button type="submit" class="button">Upload and Import</button>
<button type="button" class="button" onclick="document.getElementById('csv-import-form').style.display='none'">Cancel</button>
</p>
</form>
<div id="import-results"></div>
</div>
<script>
document.getElementById('csv-upload-form').addEventListener('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
var resultsDiv = document.getElementById('import-results');
resultsDiv.innerHTML = '<p>Importing...</p>';
fetch('{% url "admin_industrysector_csv_import" %}', {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
resultsDiv.innerHTML = '<p style="color: green;">✓ Import successful!<br>' +
'Created: ' + data.created + '<br>' +
'Updated: ' + data.updated + '<br>' +
(data.errors.length > 0 ? 'Errors: ' + data.errors.join('<br>') : '') +
'</p>';
setTimeout(function() {
window.location.reload();
}, 2000);
} else {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + data.error + '</p>';
}
})
.catch(error => {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + error + '</p>';
});
});
</script>
{{ block.super }}
{% endblock %}

View File

@@ -1,73 +0,0 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_urls static %}
{% block object-tools-items %}
<li>
<a href="#" class="addlink" onclick="document.getElementById('csv-import-form').style.display='block'; return false;">
Import from CSV
</a>
</li>
{{ block.super }}
{% endblock %}
{% block content %}
<div id="csv-import-form" style="display:none; background: #f8f8f8; padding: 20px; margin: 20px 0; border: 1px solid #ddd;">
<h2>Import Global Keywords from CSV</h2>
<form method="post" enctype="multipart/form-data" action="{% url 'admin_seedkeyword_csv_import' %}" id="csv-upload-form">
{% csrf_token %}
<p>
<label for="csv_file">Select CSV file:</label>
<input type="file" name="csv_file" id="csv_file" accept=".csv" required>
</p>
<p>
<strong>CSV Format:</strong> keyword, industry, sector, volume, difficulty, intent, is_active<br>
<em>Note: Use industry and sector names (not slugs)</em><br>
<strong>Intent values:</strong> Informational, Commercial, Transactional, Navigational<br>
<a href="{% url 'admin_seedkeyword_csv_template' %}" download>Download template with examples</a>
</p>
<p>
<button type="submit" class="button">Upload and Import</button>
<button type="button" class="button" onclick="document.getElementById('csv-import-form').style.display='none'">Cancel</button>
</p>
</form>
<div id="import-results"></div>
</div>
<script>
document.getElementById('csv-upload-form').addEventListener('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
var resultsDiv = document.getElementById('import-results');
resultsDiv.innerHTML = '<p>Importing...</p>';
fetch('{% url "admin_seedkeyword_csv_import" %}', {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
resultsDiv.innerHTML = '<p style="color: green;">✓ Import successful!<br>' +
'Created: ' + data.created + '<br>' +
'Updated: ' + data.updated + '<br>' +
(data.errors.length > 0 ? 'Errors: ' + data.errors.join('<br>') : '') +
'</p>';
setTimeout(function() {
window.location.reload();
}, 2000);
} else {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + data.error + '</p>';
}
})
.catch(error => {
resultsDiv.innerHTML = '<p style="color: red;">✗ Error: ' + error + '</p>';
});
});
</script>
{{ block.super }}
{% endblock %}