An unquoted attribute value ends at the first whitespace, so ``class=badge bg-danger`` is read by every browser as ``class="badge"`` plus two meaningless attributes. Bootstrap was loading perfectly well; the markup simply never asked for the styles. Across the ops portal that meant buttons rendered as plain links, status badges were invisible (white text on a white background: a failed result showed as nothing at all), the active sidebar item never highlighted, and the flex utility classes did nothing. The buyer portal templates quote their attributes, which is why only the ops portal looked unstyled. 346 attributes across 20 templates, rewritten mechanically with a conservative transform that handles the three shapes in use — a Django tag as the value, a multi-token class list, and a trailing simple conditional (the active-nav highlight) — and leaves anything it does not recognise exactly as it was.
69 lines
5.3 KiB
HTML
69 lines
5.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>{% block title %}IXG Operations{% endblock %}</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
<style>
|
|
body { font-size: .875rem; background: #f5f6fa; }
|
|
.sidebar { position: fixed; top: 0; bottom: 0; left: 0; z-index: 100; padding: 48px 0 0; width: 240px; background: #1e2a3a; }
|
|
.sidebar .nav-link { color: #a0aec0; padding: .65rem 1.25rem; font-size: .875rem; }
|
|
.sidebar .nav-link:hover, .sidebar .nav-link.active { color: #fff; background: rgba(255,255,255,.08); }
|
|
.sidebar .nav-link i { margin-right: .5rem; }
|
|
.sidebar .brand { padding: 1rem 1.25rem; font-size: 1.1rem; font-weight: 700; color: #fff; border-bottom: 1px solid rgba(255,255,255,.08); margin-bottom: .5rem; }
|
|
.main { margin-left: 240px; }
|
|
.topbar { background: #fff; border-bottom: 1px solid #e2e8f0; padding: .75rem 1.5rem; display: flex; justify-content: space-between; align-items: center; }
|
|
.content { padding: 1.5rem; }
|
|
.stat-card { background: #fff; border-radius: .5rem; padding: 1.25rem; border: 1px solid #e2e8f0; }
|
|
.stat-card .stat-value { font-size: 1.75rem; font-weight: 700; }
|
|
.stat-card .stat-label { font-size: .8rem; color: #718096; text-transform: uppercase; letter-spacing: .05em; }
|
|
.badge-status { font-size: .75rem; }
|
|
.page-header { margin-bottom: 1.5rem; }
|
|
.page-header h2 { font-weight: 600; }
|
|
.filter-bar { background: #fff; border-radius: .5rem; padding: 1rem; border: 1px solid #e2e8f0; margin-bottom: 1.5rem; }
|
|
.guide-content img { max-width: 100%; height: auto; border-radius: .375rem; }
|
|
.guide-content table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; }
|
|
.guide-content th, .guide-content td { border: 1px solid #e2e8f0; padding: .5rem .75rem; }
|
|
.guide-content pre { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: .375rem; padding: .75rem; }
|
|
.guide-content blockquote { border-left: 4px solid #a7f3d0; padding-left: 1rem; color: #475569; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="sidebar">
|
|
<div class="brand">IXG Platform</div>
|
|
<ul class="nav flex-column">
|
|
<li class="nav-item"><a class="nav-link {% if request.resolver_match.url_name == 'dashboard' %}active{% endif %}" href="{% url 'ops:dashboard' %}"><i class="bi bi-speedometer2"></i> Dashboard</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'intake' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:intake_list' %}"><i class="bi bi-basket"></i> Harvest Intakes</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'batch' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:batch_list' %}"><i class="bi bi-box-seam"></i> Batches</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'qc' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:qc_list' %}"><i class="bi bi-clipboard-check"></i> QC Results</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'verify' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:qc_verify_list' %}"><i class="bi bi-person-check"></i> QC Approvals</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'coa' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:coa_review_list' %}"><i class="bi bi-file-earmark-medical"></i> CoA Reviews</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'eudr' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:eudr_list' %}"><i class="bi bi-shield-check"></i> EUDR Compliance</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'shipment' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:shipment_list' %}"><i class="bi bi-truck"></i> Shipments</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'capa' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:capa_list' %}"><i class="bi bi-exclamation-triangle"></i> CAPA Records</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'document' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:document_list' %}"><i class="bi bi-file-earmark-text"></i> Documents</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'esg' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:esg_list' %}"><i class="bi bi-tree"></i> ESG Reports</a></li>
|
|
<li class="nav-item"><a class="nav-link {% if 'guide' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'ops:guide_index' %}"><i class="bi bi-book"></i> Help</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="main">
|
|
<div class="topbar">
|
|
<span></span>
|
|
<div class="d-flex align-items-center gap-3">
|
|
<a href="/admin/" class="text-decoration-none text-secondary"><i class="bi bi-shield-lock"></i> Admin</a>
|
|
<span class="text-secondary">{{ request.user.full_name|default:request.user.email }}</span>
|
|
<a href="{% url 'oidc_logout' %}" class="btn btn-sm btn-outline-secondary">Logout</a>
|
|
</div>
|
|
</div>
|
|
<div class="content">
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|