Skip to content

Admin-Interface

Audience: Admin
You will learn: - Administrative Funktionen des Web-Interfaces - Icon-Management und Metadaten-Verwaltung - Bulk-Operationen und Maintenance-Tools - Admin-spezifische UI-Komponenten

Pre-requisites: - Administrator-Handbuch verstanden - Frontend Web-Interface Grundlagen - Admin-Rechte auf dem System

Status: Teilweise implementiert

Hinweis

Das dedizierte Admin-Interface ist derzeit teilweise implementiert. Die meisten administrativen Funktionen werden über Command-Line-Tools und direkte File-Bearbeitung durchgeführt.

Evidenz: app.py:1-67 (kein /admin Endpunkt), replit.md administrative workflows

Aktuelle Admin-Funktionen

1. Web-Interface für Übersicht

Das Standard-Web-Interface bietet bereits grundlegende administrative Einblicke:

@app.route('/')
def index():
    """Zeigt komplette Icon-Übersicht - auch für Admins nutzbar"""
    icons, categories = get_icon_list()
    return render_template('index.html', 
                         icons=icons,
                         categories=categories,
                         total_icons=len(icons))

Admin-relevante Informationen: - Gesamtanzahl Icons: Anzeige in Header - Kategorie-Verteilung: Dropdown mit Icon-Anzahl pro Kategorie - Vollständige Icon-Liste: Alle verfügbaren Icons mit Metadaten

Evidenz: app.py:45-49

2. API für administrative Abfragen

@app.route('/api/icons')
def api_icons():
    """API-Endpunkt für programmatische Admin-Tools"""
    icons, categories = get_icon_list()
    return jsonify({
        'icons': icons,
        'categories': categories,
        'metadata': {
            'total_icons': len(icons),
            'total_categories': len(categories),
            'timestamp': time.time()
        }
    })

Administrative API-Nutzung:

# Icon-Anzahl prüfen
curl -s http://localhost:5000/api/icons | jq '.metadata.total_icons'

# Kategorie-Konsistenz prüfen
curl -s http://localhost:5000/api/icons | jq '.categories | keys[]'

Evidenz: app.py:51-55

Geplante Admin-Interface Features

1. Admin Dashboard

<!-- Geplant: /admin Route -->
<div class="admin-dashboard">
    <div class="stats-grid">
        <div class="stat-card">
            <h3>{{ total_icons }}</h3>
            <p>Total Icons</p>
        </div>
        <div class="stat-card">
            <h3>{{ categories|length }}</h3>
            <p>Kategorien</p>
        </div>
        <div class="stat-card">
            <h3>{{ zip_size }}</h3>
            <p>ZIP Größe</p>
        </div>
    </div>

    <div class="recent-changes">
        <h2>Letzte Änderungen</h2>
        <!-- Git commits oder File-Timestamps -->
    </div>

    <div class="system-health">
        <h2>System Status</h2>
        <div class="health-checks">
            <div class="check {{ 'ok' if icons_dir_exists else 'error' }}">
                Icons Directory: {{ 'OK' if icons_dir_exists else 'ERROR' }}
            </div>
            <div class="check {{ 'ok' if metadata_valid else 'error' }}">
                Metadaten: {{ 'Valid' if metadata_valid else 'Invalid' }}
            </div>
        </div>
    </div>
</div>

2. Icon-Upload Interface

<!-- Geplant: Icon-Upload Form -->
<div class="icon-upload">
    <h2>Neue Icons hinzufügen</h2>
    <form id="icon-upload-form" enctype="multipart/form-data">
        <div class="upload-area">
            <input type="file" id="svg-file" accept=".svg" multiple>
            <label for="svg-file">SVG-Dateien auswählen</label>
        </div>

        <div class="metadata-form">
            <select name="category" required>
                <option value="">Kategorie wählen</option>
                {% for category in categories %}
                <option value="{{ category }}">{{ category }}</option>
                {% endfor %}
            </select>

            <input type="text" name="custom-category" placeholder="Neue Kategorie">

            <div class="icon-preview">
                <!-- Dynamic preview of uploaded SVGs -->
            </div>
        </div>

        <button type="submit">Icons hinzufügen</button>
    </form>
</div>

3. Kategorie-Management

<!-- Geplant: Kategorie-Editor -->
<div class="category-management">
    <h2>Kategorien verwalten</h2>

    <div class="category-list">
        {% for category, icon_list in categories.items() %}
        <div class="category-item">
            <div class="category-header">
                <h3 contenteditable="true">{{ category }}</h3>
                <span class="icon-count">{{ icon_list|length }} Icons</span>
                <button class="delete-category">🗑️</button>
            </div>

            <div class="category-icons">
                {% for icon_filename in icon_list %}
                <div class="icon-item" data-filename="{{ icon_filename }}">
                    <img src="/static/icons/{{ icon_filename }}" alt="{{ icon_filename }}">
                    <span>{{ icon_filename }}</span>
                    <button class="move-icon">↗️</button>
                </div>
                {% endfor %}
            </div>
        </div>
        {% endfor %}
    </div>

    <div class="add-category">
        <input type="text" placeholder="Neue Kategorie" id="new-category">
        <button onclick="addCategory()">Hinzufügen</button>
    </div>
</div>

Command-Line Admin-Tools

1. System-Health-Check

#!/bin/bash
# scripts/admin-health-check.sh

echo "=== Icon System Health Check ==="

# Icons Directory Check
if [ -d "static/icons" ]; then
    icon_count=$(ls static/icons/*.svg | wc -l)
    echo "✓ Icons Directory: $icon_count SVG files"
else
    echo "❌ Icons Directory: Missing"
    exit 1
fi

# Metadata Check
if [ -f "icons.json" ]; then
    if python3 -c "import json; json.load(open('icons.json'))" 2>/dev/null; then
        echo "✓ Metadata: Valid JSON"
    else
        echo "❌ Metadata: Invalid JSON"
        exit 1
    fi
else
    echo "❌ Metadata: icons.json missing"
    exit 1
fi

# Consistency Check
python3 -c "
import json, os
with open('icons.json') as f:
    categories = json.load(f)

categorized = set()
for cat_icons in categories.values():
    categorized.update(cat_icons)

actual = set(os.listdir('static/icons'))
uncategorized = actual - categorized
missing = categorized - actual

if uncategorized:
    print(f'⚠️  Uncategorized: {len(uncategorized)} icons')
if missing:
    print(f'❌ Missing: {len(missing)} categorized icons not found')
if not uncategorized and not missing:
    print('✓ Categorization: Consistent')
"

echo "=== Health Check Complete ==="

Evidenz: Administrative workflows aus replit.md:81-91

2. Bulk-Icon-Operations

# scripts/bulk-admin.py
import json
import os
import shutil
from pathlib import Path

class IconAdmin:
    def __init__(self):
        self.icons_dir = Path('static/icons')
        self.metadata_file = Path('icons.json')

    def validate_consistency(self):
        """Check consistency between files and metadata"""
        with open(self.metadata_file) as f:
            categories = json.load(f)

        categorized = set()
        for cat_icons in categories.values():
            categorized.update(cat_icons)

        actual = set(f.name for f in self.icons_dir.glob('*.svg'))

        return {
            'uncategorized': actual - categorized,
            'missing': categorized - actual,
            'total_files': len(actual),
            'total_categorized': len(categorized)
        }

    def move_icons_to_category(self, icon_files, target_category):
        """Move multiple icons to a new category"""
        with open(self.metadata_file, 'r') as f:
            categories = json.load(f)

        # Remove from old categories
        for category in categories.values():
            for icon_file in icon_files:
                if icon_file in category:
                    category.remove(icon_file)

        # Add to new category
        if target_category not in categories:
            categories[target_category] = []

        categories[target_category].extend(icon_files)

        # Save updated metadata
        with open(self.metadata_file, 'w') as f:
            json.dump(categories, f, indent=2)

    def remove_icons(self, icon_files):
        """Remove icons from both filesystem and metadata"""
        # Remove files
        for icon_file in icon_files:
            icon_path = self.icons_dir / icon_file
            if icon_path.exists():
                icon_path.unlink()

        # Remove from metadata
        with open(self.metadata_file, 'r') as f:
            categories = json.load(f)

        for category in categories.values():
            for icon_file in icon_files:
                if icon_file in category:
                    category.remove(icon_file)

        with open(self.metadata_file, 'w') as f:
            json.dump(categories, f, indent=2)

# Usage
admin = IconAdmin()
consistency = admin.validate_consistency()
print(f"Consistency Report: {consistency}")

3. Automated Icon-Updates

#!/bin/bash
# scripts/update-fontawesome.sh

echo "Updating FontAwesome dependencies..."

# Update Node.js dependencies
npm update @fortawesome/fontawesome-svg-core
npm update @fortawesome/free-solid-svg-icons

# Backup current icons
backup_dir="backup-$(date +%Y%m%d-%H%M%S)"
mkdir "$backup_dir"
cp -r static/icons "$backup_dir/"
cp icons.json "$backup_dir/"

# Extract new icons
node extract-icons.js

# Validate new extraction
new_count=$(ls static/icons/*.svg | wc -l)
old_count=$(ls "$backup_dir/icons"/*.svg | wc -l)

echo "Icon count: $old_count$new_count"

if [ "$new_count" -lt "$old_count" ]; then
    echo "⚠️  Icon count decreased, manual review recommended"
fi

# Run health check
./scripts/admin-health-check.sh

echo "Update complete. Backup available in $backup_dir"

Admin API-Erweiterungen

1. System-Status API

# Geplant: Admin-spezifische Endpunkte
@app.route('/api/admin/status')
def admin_status():
    """System status for administrators"""
    icons, categories = get_icon_list()

    # File system stats
    icons_dir = Path('static/icons')
    total_size = sum(f.stat().st_size for f in icons_dir.glob('*.svg'))

    # Git information (if available)
    try:
        import subprocess
        last_commit = subprocess.check_output(
            ['git', 'log', '-1', '--format=%h %s'], 
            universal_newlines=True
        ).strip()
    except:
        last_commit = "Unknown"

    return jsonify({
        'system': {
            'total_icons': len(icons),
            'total_categories': len(categories),
            'total_size_bytes': total_size,
            'last_commit': last_commit,
            'timestamp': time.time()
        },
        'health': {
            'icons_directory': icons_dir.exists(),
            'metadata_file': Path('icons.json').exists(),
            'consistency': validate_consistency()
        }
    })

@app.route('/api/admin/categories', methods=['POST'])
def update_categories():
    """Update category metadata"""
    new_categories = request.json

    # Validate category structure
    if not isinstance(new_categories, dict):
        return jsonify({'error': 'Invalid category format'}), 400

    # Backup current metadata
    backup_metadata()

    # Save new categories
    with open('icons.json', 'w') as f:
        json.dump(new_categories, f, indent=2)

    return jsonify({'success': True, 'categories': len(new_categories)})

2. Batch-Upload API

@app.route('/api/admin/upload', methods=['POST'])
def upload_icons():
    """Upload new SVG icons"""
    if 'icons' not in request.files:
        return jsonify({'error': 'No icons provided'}), 400

    uploaded_files = request.files.getlist('icons')
    category = request.form.get('category', 'Uncategorized')

    results = []
    for file in uploaded_files:
        if file.filename.endswith('.svg'):
            # Validate SVG content
            if validate_svg(file):
                # Save file
                file.save(f'static/icons/{file.filename}')

                # Update metadata
                add_to_category(file.filename, category)

                results.append({'filename': file.filename, 'status': 'success'})
            else:
                results.append({'filename': file.filename, 'status': 'invalid_svg'})
        else:
            results.append({'filename': file.filename, 'status': 'not_svg'})

    return jsonify({'results': results})

Security für Admin-Interface

1. Authentifizierung

# Geplant: Basic Authentication für Admin-Bereiche
from functools import wraps
from flask import request, Response

def check_auth(username, password):
    """Check if username/password combination is valid"""
    # In production: use proper password hashing
    return username == 'admin' and password == os.environ.get('ADMIN_PASSWORD', 'changeme')

def authenticate():
    """Send 401 response that enables basic auth"""
    return Response(
        'Authentication required', 401,
        {'WWW-Authenticate': 'Basic realm="Admin Area"'}
    )

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            return authenticate()
        return f(*args, **kwargs)
    return decorated

# Protect admin routes
@app.route('/admin')
@requires_auth
def admin_dashboard():
    return render_template('admin/dashboard.html')

2. CSRF-Protection

# Geplant: CSRF-Token für Admin-Formulare
import secrets

@app.before_request
def csrf_protection():
    if request.method == "POST" and request.endpoint and 'admin' in request.endpoint:
        token = request.form.get('csrf_token')
        if not token or token != session.get('csrf_token'):
            abort(403)

@app.route('/admin')
def admin_dashboard():
    session['csrf_token'] = secrets.token_hex(16)
    return render_template('admin/dashboard.html')

Deployment-Überlegungen

1. Admin-Interface aktivieren

# Admin-Mode über Environment Variable
ADMIN_ENABLED = os.environ.get('ADMIN_ENABLED', 'false').lower() == 'true'

if ADMIN_ENABLED:
    # Register admin blueprints
    from admin import admin_bp
    app.register_blueprint(admin_bp, url_prefix='/admin')

2. Production-Sicherheit

# Environment-Variablen für Production
export ADMIN_ENABLED=true
export ADMIN_PASSWORD=secure_random_password
export FLASK_ENV=production
export SECRET_KEY=your_secret_key

Roadmap

Phase 1: Grundlegende Admin-UI (geplant)

  • [ ] Admin-Dashboard mit System-Status
  • [ ] Kategorie-Management Interface
  • [ ] Basic Authentication

Phase 2: Erweiterte Features (future)

  • [ ] Icon-Upload über Web-Interface
  • [ ] Bulk-Operations UI
  • [ ] Git-Integration für Changes

Phase 3: Enterprise Features (future)

  • [ ] User-Management
  • [ ] Audit-Logs
  • [ ] Advanced Analytics

Evidenz: Development roadmap aus replit.md:91


Unknown (not found): Vollständiges Admin-Interface UI. Next step: Implementierung basierend auf Admin-Workflows aus Administrator-Handbuch

Related: - Administrator-Handbuch für Workflow-Details - Backend-Übersicht für API-Erweiterungen - Operations-Runbook für Production-Setup