#!/usr/bin/env python3 """ SecuBox Evolution Dashboard Interactive Streamlit landing page showing project evolution, history, WIP, TODO, and README """ import streamlit as st import requests import re from datetime import datetime from collections import Counter # Page config st.set_page_config( page_title="SecuBox Evolution", page_icon="🛡️", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for dark cyberpunk theme st.markdown(""" """, unsafe_allow_html=True) # GitHub raw URLs GITHUB_BASE = "https://raw.githubusercontent.com/gkerma/secubox-openwrt/master" FILES = { "HISTORY": f"{GITHUB_BASE}/.claude/HISTORY.md", "WIP": f"{GITHUB_BASE}/.claude/WIP.md", "TODO": f"{GITHUB_BASE}/.claude/TODO.md", "README": f"{GITHUB_BASE}/README.md" } @st.cache_data(ttl=300) def fetch_file(url): """Fetch file content from GitHub""" try: response = requests.get(url, timeout=10) if response.status_code == 200: return response.text return None except: return None def parse_history(content): """Parse HISTORY.md to extract milestones""" if not content: return [] milestones = [] # Match patterns like "1. **Title (2026-02-06)**" or "14. **P2P MirrorBox..." pattern = r'(\d+)\.\s+\*\*([^*]+)\*\*' for match in re.finditer(pattern, content): num = match.group(1) title = match.group(2).strip() # Extract date if present date_match = re.search(r'\((\d{4}-\d{2}-\d{2})\)', title) date = date_match.group(1) if date_match else None title_clean = re.sub(r'\s*\(\d{4}-\d{2}-\d{2}\)\s*', '', title) milestones.append({ 'num': int(num), 'title': title_clean, 'date': date }) return milestones def parse_packages(content): """Extract package names from content""" if not content: return [] packages = set() # Match `package-name` or secubox-app-xxx patterns patterns = [ r'`(secubox-[a-z0-9-]+)`', r'`(luci-app-[a-z0-9-]+)`', r'\*\*([a-z0-9-]+)\*\*:', ] for pattern in patterns: for match in re.finditer(pattern, content): pkg = match.group(1) if len(pkg) > 3: packages.add(pkg) return list(packages) def count_features(content): """Count features mentioned in content""" if not content: return {} features = { 'AI/LocalAI': len(re.findall(r'LocalAI|AI-powered|LLM|agent', content, re.I)), 'Security': len(re.findall(r'CrowdSec|WAF|firewall|threat|CVE|security', content, re.I)), 'DNS': len(re.findall(r'DNS|Vortex|dnsctl|AdGuard', content, re.I)), 'Mesh/P2P': len(re.findall(r'mesh|P2P|gossip|mirror|peer', content, re.I)), 'Containers': len(re.findall(r'LXC|Docker|container', content, re.I)), 'UI/LuCI': len(re.findall(r'LuCI|dashboard|UI|interface', content, re.I)), } return features def main(): # Header st.markdown('

🛡️ SecuBox Evolution

', unsafe_allow_html=True) st.markdown('

Real-time project tracking • History • WIP • TODO • Documentation

', unsafe_allow_html=True) # Fetch all files with st.spinner("Fetching latest data from GitHub..."): history = fetch_file(FILES["HISTORY"]) wip = fetch_file(FILES["WIP"]) todo = fetch_file(FILES["TODO"]) readme = fetch_file(FILES["README"]) # Parse data milestones = parse_history(history) packages = parse_packages(history or "") features = count_features(history or "") # Metrics row col1, col2, col3, col4 = st.columns(4) with col1: st.markdown(f"""
{len(milestones)}
Milestones
""", unsafe_allow_html=True) with col2: st.markdown(f"""
{len(packages)}
Packages
""", unsafe_allow_html=True) with col3: # Count TODO items todo_count = len(re.findall(r'^- \[[ x]\]', todo or "", re.M)) st.markdown(f"""
{todo_count}
TODO Items
""", unsafe_allow_html=True) with col4: # Latest date latest_date = "N/A" for m in reversed(milestones): if m['date']: latest_date = m['date'] break st.markdown(f"""
{latest_date}
Last Update
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # Sidebar with st.sidebar: st.markdown("### 🔍 Search") search_query = st.text_input("Search in all files", placeholder="e.g., CrowdSec, HAProxy...") st.markdown("### 📊 Feature Distribution") if features: for feat, count in sorted(features.items(), key=lambda x: -x[1]): if count > 0: st.progress(min(count / 50, 1.0), text=f"{feat}: {count}") st.markdown("### 🏷️ Recent Packages") for pkg in packages[-10:]: st.markdown(f'{pkg}', unsafe_allow_html=True) st.markdown("---") st.markdown("### ⚡ Quick Links") st.markdown("[GitHub Repository](https://github.com/gkerma/secubox-openwrt)") st.markdown("[SecuBox Portal](https://secubox.in)") if st.button("🔄 Refresh Data"): st.cache_data.clear() st.rerun() # Main tabs tab1, tab2, tab3, tab4, tab5 = st.tabs(["📜 History", "🔧 WIP", "📋 TODO", "📖 README", "📈 Timeline"]) with tab1: st.markdown("## 📜 Project History") if search_query and history: # Highlight search results highlighted = history.replace(search_query, f'**:green[{search_query}]**') st.markdown(highlighted) elif history: # Show milestones as cards for m in reversed(milestones[-20:]): date_str = f"📅 {m['date']}" if m['date'] else "" st.markdown(f"""
{date_str}
{m['num']}. {m['title']}
""", unsafe_allow_html=True) with st.expander("📄 View Full History"): st.markdown(history) else: st.error("Could not fetch HISTORY.md") with tab2: st.markdown("## 🔧 Work In Progress") if search_query and wip: highlighted = wip.replace(search_query, f'**:orange[{search_query}]**') st.markdown(highlighted) elif wip: st.markdown(wip) else: st.error("Could not fetch WIP.md") with tab3: st.markdown("## 📋 TODO List") if search_query and todo: highlighted = todo.replace(search_query, f'**:yellow[{search_query}]**') st.markdown(highlighted) elif todo: # Parse and display TODO items lines = todo.split('\n') completed = 0 pending = 0 for line in lines: if re.match(r'^- \[x\]', line): completed += 1 elif re.match(r'^- \[ \]', line): pending += 1 col1, col2 = st.columns(2) with col1: st.metric("✅ Completed", completed) with col2: st.metric("⏳ Pending", pending) if completed + pending > 0: progress = completed / (completed + pending) st.progress(progress, text=f"Progress: {progress*100:.1f}%") st.markdown("---") st.markdown(todo) else: st.error("Could not fetch TODO.md") with tab4: st.markdown("## 📖 README") if search_query and readme: highlighted = readme.replace(search_query, f'**:blue[{search_query}]**') st.markdown(highlighted) elif readme: st.markdown(readme) else: st.error("Could not fetch README.md") with tab5: st.markdown("## 📈 Evolution Timeline") if milestones: # Group by month months = {} for m in milestones: if m['date']: month = m['date'][:7] # YYYY-MM if month not in months: months[month] = [] months[month].append(m) # Display timeline for month in sorted(months.keys(), reverse=True): items = months[month] month_name = datetime.strptime(month, "%Y-%m").strftime("%B %Y") st.markdown(f"### 📅 {month_name}") for item in items: st.markdown(f"""
{item['title']}
Milestone #{item['num']}
""", unsafe_allow_html=True) # Chart st.markdown("### 📊 Milestones per Month") month_counts = {m: len(items) for m, items in months.items()} if month_counts: import pandas as pd df = pd.DataFrame(list(month_counts.items()), columns=['Month', 'Count']) df = df.sort_values('Month') st.bar_chart(df.set_index('Month')) else: st.info("No dated milestones found in history") # Footer st.markdown("---") st.markdown("""
SecuBox Evolution Dashboard • Auto-synced with GitHub master branch
Data refreshes every 5 minutes • View on GitHub
""", unsafe_allow_html=True) if __name__ == "__main__": main()