Add development testing environment

Templates (8 basic templates):
- base.html: Main layout with navigation, flash messages, responsive design
- login.html: User login form with remember me option
- register.html: User registration with validation
- dashboard.html: Main dashboard with statistics cards and recent activity
- players_list.html: Players list placeholder
- add_player.html: Add player form
- groups_list.html: Groups list placeholder
- create_group.html: Create group form
- content_list.html: Content list placeholder
- upload_content.html: File upload form
- admin.html: Admin panel with system overview

Development Setup:
- run_dev.sh: Automated development server setup script
  - Creates virtual environment
  - Installs dependencies
  - Initializes database
  - Creates default admin user (admin/admin123)
  - Runs Flask development server on port 5000

Static Files:
- static/uploads/ directory with .gitkeep
- Ready for media file uploads

Testing Features:
 Basic navigation and routing
 Authentication flow (login/register/logout)
 Dashboard with statistics
 Flash message system
 Responsive design with clean UI
 Placeholder templates for all routes

Ready for manual testing at http://localhost:5000
This commit is contained in:
ske087
2025-11-12 10:39:25 +02:00
parent 53ab7fa4ab
commit 2deb398fd8
13 changed files with 478 additions and 0 deletions

View File

@@ -0,0 +1 @@
# This file ensures the uploads directory is tracked by git even when empty

View File

@@ -0,0 +1,30 @@
{% extends "base.html" %}
{% block title %}Add Player - DigiServer v2{% endblock %}
{% block content %}
<h1>Add Player</h1>
<div class="card">
<form method="POST">
<div style="margin-bottom: 1rem;">
<label>Name</label>
<input type="text" name="name" required style="width: 100%; padding: 0.5rem;">
</div>
<div style="margin-bottom: 1rem;">
<label>Location (optional)</label>
<input type="text" name="location" style="width: 100%; padding: 0.5rem;">
</div>
<div style="margin-bottom: 1rem;">
<label>Group (optional)</label>
<select name="group_id" style="width: 100%; padding: 0.5rem;">
<option value="">No Group</option>
{% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-success">Create Player</button>
<a href="{{ url_for('players.players_list') }}" class="btn">Cancel</a>
</form>
</div>
{% endblock %}

20
app/templates/admin.html Normal file
View File

@@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block title %}Admin Panel - DigiServer v2{% endblock %}
{% block content %}
<h1>Admin Panel</h1>
<div class="card">
<h2>System Overview</h2>
<p>Total Users: {{ total_users or 0 }}</p>
<p>Total Players: {{ total_players or 0 }}</p>
<p>Total Groups: {{ total_groups or 0 }}</p>
<p>Total Content: {{ total_content or 0 }}</p>
<p>Storage Used: {{ storage_mb or 0 }} MB</p>
</div>
<div class="card">
<h2>User Management</h2>
<p>User management features - Template in progress</p>
</div>
{% endblock %}

145
app/templates/base.html Normal file
View File

@@ -0,0 +1,145 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}DigiServer v2{% endblock %}</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
line-height: 1.6;
color: #333;
background: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background: #2c3e50;
color: white;
padding: 1rem 0;
margin-bottom: 2rem;
}
header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
header h1 { font-size: 1.5rem; }
nav a {
color: white;
text-decoration: none;
margin-left: 1rem;
padding: 0.5rem 1rem;
border-radius: 4px;
transition: background 0.3s;
}
nav a:hover { background: rgba(255,255,255,0.1); }
.alert {
padding: 1rem;
margin-bottom: 1rem;
border-radius: 4px;
border-left: 4px solid;
}
.alert-success {
background: #d4edda;
border-color: #28a745;
color: #155724;
}
.alert-danger {
background: #f8d7da;
border-color: #dc3545;
color: #721c24;
}
.alert-warning {
background: #fff3cd;
border-color: #ffc107;
color: #856404;
}
.alert-info {
background: #d1ecf1;
border-color: #17a2b8;
color: #0c5460;
}
.card {
background: white;
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 1rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.card h2 { margin-bottom: 1rem; color: #2c3e50; }
.btn {
display: inline-block;
padding: 0.5rem 1rem;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 4px;
border: none;
cursor: pointer;
transition: background 0.3s;
}
.btn:hover { background: #2980b9; }
.btn-danger { background: #e74c3c; }
.btn-danger:hover { background: #c0392b; }
.btn-success { background: #27ae60; }
.btn-success:hover { background: #229954; }
footer {
margin-top: 2rem;
padding: 1rem 0;
text-align: center;
color: #7f8c8d;
font-size: 0.9rem;
}
</style>
{% block extra_css %}{% endblock %}
</head>
<body>
<header>
<div class="container">
<h1>📺 DigiServer v2</h1>
<nav>
{% if current_user.is_authenticated %}
<a href="{{ url_for('main.dashboard') }}">Dashboard</a>
<a href="{{ url_for('players.players_list') }}">Players</a>
<a href="{{ url_for('groups.groups_list') }}">Groups</a>
<a href="{{ url_for('content.content_list') }}">Content</a>
{% if current_user.is_admin %}
<a href="{{ url_for('admin.admin_panel') }}">Admin</a>
{% endif %}
<a href="{{ url_for('auth.logout') }}">Logout ({{ current_user.username }})</a>
{% else %}
<a href="{{ url_for('auth.login') }}">Login</a>
<a href="{{ url_for('auth.register') }}">Register</a>
{% endif %}
</nav>
</div>
</header>
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<footer>
<div class="container">
DigiServer v2.0.0-alpha | Blueprint Architecture | {{ server_version if server_version else 'Development' }}
</div>
</footer>
{% block extra_js %}{% endblock %}
</body>
</html>

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Content - DigiServer v2{% endblock %}
{% block content %}
<h1>Content</h1>
<div class="card">
<p>Content list view - Template in progress</p>
<a href="{{ url_for('content.upload_content') }}" class="btn btn-success">Upload Content</a>
</div>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends "base.html" %}
{% block title %}Create Group - DigiServer v2{% endblock %}
{% block content %}
<h1>Create Group</h1>
<div class="card">
<form method="POST">
<div style="margin-bottom: 1rem;">
<label>Group Name</label>
<input type="text" name="name" required style="width: 100%; padding: 0.5rem;">
</div>
<div style="margin-bottom: 1rem;">
<label>Description (optional)</label>
<textarea name="description" rows="3" style="width: 100%; padding: 0.5rem;"></textarea>
</div>
<button type="submit" class="btn btn-success">Create Group</button>
<a href="{{ url_for('groups.groups_list') }}" class="btn">Cancel</a>
</form>
</div>
{% endblock %}

View File

@@ -0,0 +1,69 @@
{% extends "base.html" %}
{% block title %}Dashboard - DigiServer v2{% endblock %}
{% block content %}
<h1 style="margin-bottom: 2rem;">Dashboard</h1>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem; margin-bottom: 2rem;">
<div class="card">
<h3 style="color: #3498db; margin-bottom: 0.5rem;">👥 Players</h3>
<p style="font-size: 2rem; font-weight: bold;">{{ total_players or 0 }}</p>
<a href="{{ url_for('players.players_list') }}" class="btn" style="margin-top: 1rem;">View Players</a>
</div>
<div class="card">
<h3 style="color: #9b59b6; margin-bottom: 0.5rem;">📁 Groups</h3>
<p style="font-size: 2rem; font-weight: bold;">{{ total_groups or 0 }}</p>
<a href="{{ url_for('groups.groups_list') }}" class="btn" style="margin-top: 1rem;">View Groups</a>
</div>
<div class="card">
<h3 style="color: #e67e22; margin-bottom: 0.5rem;">🎬 Content</h3>
<p style="font-size: 2rem; font-weight: bold;">{{ total_content or 0 }}</p>
<a href="{{ url_for('content.content_list') }}" class="btn" style="margin-top: 1rem;">View Content</a>
</div>
<div class="card">
<h3 style="color: #27ae60; margin-bottom: 0.5rem;">💾 Storage</h3>
<p style="font-size: 2rem; font-weight: bold;">{{ storage_mb or 0 }} MB</p>
<a href="{{ url_for('content.upload_content') }}" class="btn btn-success" style="margin-top: 1rem;">Upload Content</a>
</div>
</div>
<div class="card">
<h2>Quick Actions</h2>
<div style="display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 1rem;">
<a href="{{ url_for('players.add_player') }}" class="btn btn-success"> Add Player</a>
<a href="{{ url_for('groups.create_group') }}" class="btn btn-success"> Create Group</a>
<a href="{{ url_for('content.upload_content') }}" class="btn btn-success">⬆️ Upload Content</a>
{% if current_user.is_admin %}
<a href="{{ url_for('admin.admin_panel') }}" class="btn">⚙️ Admin Panel</a>
{% endif %}
</div>
</div>
{% if recent_logs %}
<div class="card">
<h2>Recent Activity</h2>
<div style="margin-top: 1rem;">
{% for log in recent_logs %}
<div style="padding: 0.5rem; border-bottom: 1px solid #eee;">
<span style="color: {% if log.level == 'error' %}#e74c3c{% elif log.level == 'warning' %}#f39c12{% else %}#27ae60{% endif %}; font-weight: bold;">
[{{ log.level.upper() }}]
</span>
{{ log.message }}
<small style="color: #7f8c8d; float: right;">{{ log.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</small>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<div class="card">
<h2>System Status</h2>
<p>✅ All systems operational</p>
<p>🔄 Blueprint architecture active</p>
<p>⚡ Flask {{ config.get('FLASK_VERSION', '3.1.0') }}</p>
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Groups - DigiServer v2{% endblock %}
{% block content %}
<h1>Groups</h1>
<div class="card">
<p>Groups list view - Template in progress</p>
<a href="{{ url_for('groups.create_group') }}" class="btn btn-success">Create New Group</a>
</div>
{% endblock %}

31
app/templates/login.html Normal file
View File

@@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block title %}Login - DigiServer v2{% endblock %}
{% block content %}
<div class="card" style="max-width: 400px; margin: 2rem auto;">
<h2>Login</h2>
<form method="POST" action="{{ url_for('auth.login') }}">
<div style="margin-bottom: 1rem;">
<label for="username" style="display: block; margin-bottom: 0.5rem;">Username</label>
<input type="text" id="username" name="username" required
style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
</div>
<div style="margin-bottom: 1rem;">
<label for="password" style="display: block; margin-bottom: 0.5rem;">Password</label>
<input type="password" id="password" name="password" required
style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
</div>
<div style="margin-bottom: 1rem;">
<label>
<input type="checkbox" name="remember" value="yes">
Remember me
</label>
</div>
<button type="submit" class="btn" style="width: 100%;">Login</button>
</form>
<p style="margin-top: 1rem; text-align: center;">
Don't have an account? <a href="{{ url_for('auth.register') }}">Register here</a>
</p>
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Players - DigiServer v2{% endblock %}
{% block content %}
<h1>Players</h1>
<div class="card">
<p>Players list view - Template in progress</p>
<a href="{{ url_for('players.add_player') }}" class="btn btn-success">Add New Player</a>
</div>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "base.html" %}
{% block title %}Register - DigiServer v2{% endblock %}
{% block content %}
<div class="card" style="max-width: 400px; margin: 2rem auto;">
<h2>Register</h2>
<form method="POST" action="{{ url_for('auth.register') }}">
<div style="margin-bottom: 1rem;">
<label for="username" style="display: block; margin-bottom: 0.5rem;">Username</label>
<input type="text" id="username" name="username" required minlength="3"
style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
<small style="color: #7f8c8d;">Minimum 3 characters</small>
</div>
<div style="margin-bottom: 1rem;">
<label for="password" style="display: block; margin-bottom: 0.5rem;">Password</label>
<input type="password" id="password" name="password" required minlength="6"
style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
<small style="color: #7f8c8d;">Minimum 6 characters</small>
</div>
<button type="submit" class="btn btn-success" style="width: 100%;">Register</button>
</form>
<p style="margin-top: 1rem; text-align: center;">
Already have an account? <a href="{{ url_for('auth.login') }}">Login here</a>
</p>
</div>
{% endblock %}

View File

@@ -0,0 +1,25 @@
{% extends "base.html" %}
{% block title %}Upload Content - DigiServer v2{% endblock %}
{% block content %}
<h1>Upload Content</h1>
<div class="card">
<form method="POST" enctype="multipart/form-data">
<div style="margin-bottom: 1rem;">
<label>File</label>
<input type="file" name="file" required style="width: 100%; padding: 0.5rem;">
</div>
<div style="margin-bottom: 1rem;">
<label>Duration (seconds, for images)</label>
<input type="number" name="duration" value="10" min="1" style="width: 100%; padding: 0.5rem;">
</div>
<div style="margin-bottom: 1rem;">
<label>Description (optional)</label>
<textarea name="description" rows="3" style="width: 100%; padding: 0.5rem;"></textarea>
</div>
<button type="submit" class="btn btn-success">Upload</button>
<a href="{{ url_for('content.content_list') }}" class="btn">Cancel</a>
</form>
</div>
{% endblock %}

76
run_dev.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# DigiServer v2 - Development Test Runner
# This script sets up and runs the application in development mode
set -e
echo "================================================"
echo " DigiServer v2 - Development Environment"
echo "================================================"
echo ""
# Check if we're in the right directory
if [ ! -f "requirements.txt" ]; then
echo "❌ Error: requirements.txt not found. Run this from the digiserver-v2 directory."
exit 1
fi
# Check if virtual environment exists
if [ ! -d "venv" ]; then
echo "📦 Creating virtual environment..."
python3 -m venv venv
echo "✅ Virtual environment created"
else
echo "✅ Virtual environment found"
fi
# Activate virtual environment
echo "🔄 Activating virtual environment..."
source venv/bin/activate
# Install/update dependencies
echo "📥 Installing dependencies..."
pip install -q --upgrade pip
pip install -q -r requirements.txt
echo "✅ Dependencies installed"
echo ""
# Check if .env exists
if [ ! -f ".env" ]; then
echo "⚠️ Warning: .env file not found, using .env.example"
cp .env.example .env
fi
# Initialize database if it doesn't exist
if [ ! -f "instance/dashboard.db" ]; then
echo "🗄️ Initializing database..."
export FLASK_APP=app.app:create_app
flask init-db
echo "✅ Database initialized"
echo "👤 Creating default admin user..."
flask create-admin
echo "✅ Admin user created (username: admin, password: admin123)"
else
echo "✅ Database found"
fi
echo ""
echo "================================================"
echo " Starting Flask Development Server"
echo "================================================"
echo ""
echo "🌐 Server will be available at: http://localhost:5000"
echo "👤 Default admin: username=admin, password=admin123"
echo ""
echo "Press Ctrl+C to stop the server"
echo ""
# Set Flask environment
export FLASK_APP=app.app:create_app
export FLASK_ENV=development
# Run Flask
flask run --host=0.0.0.0 --port=5000