Initial commit: enterprise digital platform with portal SSO, DigiServer, IT Assets, NetworkView, Server Monitor

This commit is contained in:
ske087
2026-05-10 21:07:50 +03:00
commit 8d9df56b0b
364 changed files with 73655 additions and 0 deletions
@@ -0,0 +1,227 @@
{% extends "base.html" %}
{% block title %}{{ player.name }} - DigiServer v2{% endblock %}
{% block content %}
<div class="container" style="max-width: 1400px;">
<!-- Header -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<div>
<h1>{{ player.name }}</h1>
<div style="margin-top: 10px;">
{% if status_info.online %}
<span style="background: #28a745; color: white; padding: 5px 12px; border-radius: 3px; font-size: 14px; margin-right: 10px;">
🟢 Online
</span>
{% else %}
<span style="background: #6c757d; color: white; padding: 5px 12px; border-radius: 3px; font-size: 14px; margin-right: 10px;">
⚫ Offline
</span>
{% endif %}
<span style="color: #6c757d; font-size: 14px;">
Last seen: {{ status_info.last_seen_ago }}
</span>
</div>
</div>
<div>
<a href="{{ url_for('players.edit_player', player_id=player.id) }}" class="btn btn-primary">
✏️ Edit Player
</a>
<a href="{{ url_for('playlist.manage_playlist', player_id=player.id) }}" class="btn btn-success">
🎬 Manage Playlist
</a>
<a href="{{ url_for('players.list') }}" class="btn">
← Back to Players
</a>
</div>
</div>
<!-- Main Content Grid -->
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
<!-- Player Information Card -->
<div class="card">
<h3 style="margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #dee2e6;">
📋 Player Information
</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold; width: 40%;">Display Name:</td>
<td style="padding: 10px;">{{ player.name }}</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Hostname:</td>
<td style="padding: 10px;">
<code style="background: #f8f9fa; padding: 3px 8px; border-radius: 3px;">{{ player.hostname }}</code>
</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Location:</td>
<td style="padding: 10px;">{{ player.location or '-' }}</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Orientation:</td>
<td style="padding: 10px;">{{ player.orientation or 'Landscape' }}</td>
</tr>
<tr>
<td style="padding: 10px; font-weight: bold;">Created:</td>
<td style="padding: 10px;">{{ player.created_at | localtime }}</td>
</tr>
</table>
</div>
<!-- Authentication Details Card -->
<div class="card">
<h3 style="margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #dee2e6;">
🔐 Authentication Details
</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold; width: 40%;">Password Set:</td>
<td style="padding: 10px;">
{% if player.password_hash %}
<span style="color: #28a745;">✓ Yes</span>
{% else %}
<span style="color: #dc3545;">✗ No</span>
{% endif %}
</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Quick Connect Code:</td>
<td style="padding: 10px;">
{% if player.quickconnect_code %}
<span style="color: #28a745;">✓ Yes</span>
{% else %}
<span style="color: #dc3545;">✗ No</span>
{% endif %}
</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Auth Code:</td>
<td style="padding: 10px;">
{% if player.auth_code %}
<span style="color: #28a745;">✓ Yes</span>
<form method="POST" action="{{ url_for('players.regenerate_auth_code', player_id=player.id) }}" style="display: inline; margin-left: 10px;">
<button type="submit" class="btn btn-sm" style="background: #ffc107; padding: 3px 8px;"
onclick="return confirm('Regenerate auth code? The player will need to authenticate again.')">
🔄 Regenerate
</button>
</form>
{% else %}
<span style="color: #dc3545;">✗ No</span>
{% endif %}
</td>
</tr>
<tr>
<td colspan="2" style="padding: 15px 10px;">
<a href="{{ url_for('players.edit_player', player_id=player.id) }}"
class="btn btn-primary" style="width: 100%; text-align: center;">
✏️ Edit Authentication Settings
</a>
</td>
</tr>
</table>
</div>
</div>
<!-- Playlist Management Card -->
<div class="card" style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0;">🎬 Playlist Management</h3>
</div>
{% if playlist %}
<div style="background: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 15px;">
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Total Items</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">{{ playlist|length }}</div>
</div>
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Total Duration</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">
{% set total_duration = namespace(value=0) %}
{% for item in playlist %}
{% set total_duration.value = total_duration.value + (item.duration or 10) %}
{% endfor %}
{{ total_duration.value }}s
</div>
</div>
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Playlist Version</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">{{ player.playlist_version }}</div>
</div>
</div>
</div>
{% endif %}
<a href="{{ url_for('playlist.manage_playlist', player_id=player.id) }}"
class="btn btn-primary"
style="display: inline-block; width: 100%; text-align: center; padding: 15px; font-size: 16px;">
🎬 Open Playlist Manager
</a>
{% if not playlist %}
<div style="background: #fff3cd; border: 1px solid #ffc107; color: #856404; padding: 15px; border-radius: 5px; text-align: center; margin-top: 15px;">
⚠️ No content in playlist. Open the playlist manager to add content.
</div>
{% endif %}
</div>
<!-- Player Activity Log Card -->
<div class="card">
<h3 style="margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #dee2e6;">
📊 Recent Activity & Feedback
</h3>
{% if recent_feedback %}
<div style="max-height: 400px; overflow-y: auto;">
<table style="width: 100%; border-collapse: collapse;">
<thead style="position: sticky; top: 0; background: white;">
<tr style="background: #f8f9fa; text-align: left;">
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Time</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Status</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Message</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Error</th>
</tr>
</thead>
<tbody>
{% for feedback in recent_feedback %}
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; white-space: nowrap;">
<small style="color: #6c757d;">{{ feedback.timestamp | localtime('%Y-%m-%d %H:%M:%S') }}</small>
</td>
<td style="padding: 10px;">
{% if feedback.status == 'playing' %}
<span style="background: #28a745; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">▶️ Playing</span>
{% elif feedback.status == 'idle' %}
<span style="background: #6c757d; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">⏸️ Idle</span>
{% elif feedback.status == 'error' %}
<span style="background: #dc3545; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">❌ Error</span>
{% else %}
<span style="background: #007bff; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">{{ feedback.status }}</span>
{% endif %}
</td>
<td style="padding: 10px;">
{{ feedback.message or '-' }}
</td>
<td style="padding: 10px;">
{% if feedback.error %}
<span style="color: #dc3545; font-family: monospace; font-size: 12px;">{{ feedback.error[:50] }}...</span>
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div style="background: #d1ecf1; border: 1px solid #bee5eb; color: #0c5460; padding: 15px; border-radius: 5px; text-align: center;">
️ No activity logs yet. The player will send feedback once it starts playing content.
</div>
{% endif %}
</div>
</div>
{% endblock %}