Enforce public/private visibility for web UI pages

Dev-only pages (sources, trends, complexity, idea-analysis, false-positives,
similarity, landscape, export) now require @admin_required and are hidden
from nav in production mode. Citations page keeps the graph public but
hides influence/BCP tabs behind --dev flag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 20:52:43 +01:00
parent dec8667193
commit ae5e5f8cbf
4 changed files with 85 additions and 8 deletions

View File

@@ -44,9 +44,10 @@
{% block content %}
<div class="mb-6">
<h1 class="text-2xl font-bold text-white">Citations & Influence</h1>
<p class="text-slate-400 text-sm mt-1">Cross-reference network, citation influence metrics, and BCP dependency analysis across {{ influence.stats.drafts_with_refs }} drafts and {{ influence.stats.total_citations }} total citations.</p>
<p class="text-slate-400 text-sm mt-1">Cross-reference network{% if influence %}, citation influence metrics, and BCP dependency analysis across {{ influence.stats.drafts_with_refs }} drafts and {{ influence.stats.total_citations }} total citations{% endif %}.</p>
</div>
{% if influence %}
<!-- Summary stats -->
<div class="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
<div class="stat-card rounded-xl border border-slate-800 p-4 relative overflow-hidden">
@@ -75,13 +76,18 @@
<div class="text-2xl font-bold text-white mt-1">{{ bcp.coverage.coverage_pct }}%</div>
</div>
</div>
{% endif %}
<!-- Tabs -->
<div class="border-b border-slate-800 mb-6">
<nav class="flex gap-6">
<button class="tab-btn active px-1 pb-3 text-sm font-medium text-slate-400" data-tab="graph">Citation Graph</button>
{% if influence %}
<button class="tab-btn px-1 pb-3 text-sm font-medium text-slate-400" data-tab="influence">Influence Analysis</button>
{% endif %}
{% if bcp %}
<button class="tab-btn px-1 pb-3 text-sm font-medium text-slate-400" data-tab="bcp">BCP Dependencies</button>
{% endif %}
</nav>
</div>
@@ -136,6 +142,7 @@
</div>
</div>
{% if influence %}
<!-- ==================== TAB 2: Influence Analysis ==================== -->
<div id="tab-influence" class="tab-panel">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
@@ -273,6 +280,9 @@
</div>
</div>
{% endif %}
{% if bcp %}
<!-- ==================== TAB 3: BCP Dependencies ==================== -->
<div id="tab-bcp" class="tab-panel">
<!-- BCP Stats -->
@@ -381,14 +391,15 @@
<div id="bcpHeatmap" style="height: 500px;"></div>
</div>
</div>
{% endif %}
{% endblock %}
{% block extra_scripts %}
<script>
const graph = {{ graph | tojson }};
const influence = {{ influence | tojson }};
const bcp = {{ bcp | tojson }};
{% if influence %}const influence = {{ influence | tojson }};{% endif %}
{% if bcp %}const bcp = {{ bcp | tojson }};{% endif %}
const PALETTE = [
'#3b82f6', '#ef4444', '#22c55e', '#a855f7', '#f59e0b',
@@ -635,8 +646,9 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
})();
// ===========================================================
// Plotly: Citation density by category (Tab 2)
// Plotly: Citation density by category (Tab 2) — admin only
// ===========================================================
{% if influence %}
(function() {
const cats = influence.citations_by_category;
if (!cats || cats.length === 0) return;
@@ -668,7 +680,7 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
})();
// ===========================================================
// Plotly: Draft-to-Draft Network (Tab 2)
// Plotly: Draft-to-Draft Network (Tab 2) — admin only
// ===========================================================
(function() {
const edges = influence.draft_network;
@@ -740,10 +752,12 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
showlegend: false,
}, { responsive: true, displayModeBar: false });
})();
{% endif %}
// ===========================================================
// Plotly: BCP Co-citation Heatmap (Tab 3)
// Plotly: BCP Co-citation Heatmap (Tab 3) — admin only
// ===========================================================
{% if bcp %}
(function() {
const labels = bcp.heatmap_labels;
const matrix = bcp.heatmap_matrix;
@@ -783,5 +797,6 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
yaxis: { autorange: 'reversed' },
}, { responsive: true, displayModeBar: false });
})();
{% endif %}
</script>
{% endblock %}