Files
digiserver-v2/app/templates/admin/build_player.html
T
ske087 46602f1933 Sanitize codebase, reorganize docs, and add missing deploy files
Remove dead code identified in docs/SANITIZATION-REVIEW.md:
- app/blueprints/content_old.py and app/blueprints/playlist.py
- app/models/group.py, app/utils/nginx_config_reader.py
- orphaned templates (content_list, edit_content, upload_content,
  player_page) and the related group/Template references

Result: 6 blueprints, 82 routes, no dead modules or orphan templates.

Add files that deploy.sh and docker-entrypoint.sh already require but
which were never tracked:
- https_manager.py       (referenced by deploy.sh, migrate_network.sh,
                          docker-entrypoint.sh)
- Caddyfile.example      (seeded by deploy.sh; its absence aborts deploy)

Relocate generated Graphify artifacts from graphify-out/ to
docs/graphify-out/ (110 files, no content change) and archive the
superseded docs under docs/.

Ignore hygiene:
- ignore ad-hoc .env backups (.env.bak*) — they contain live secrets
- keep the pre-sanitization snapshots (docs/legacy code/,
  docs/old_code_documentation/) on disk but out of the repo

Fix .env.example: drop a duplicated config block, genericize the
hardcoded host IP, and document HOSTNAME_INTERNAL.
2026-09-11 12:18:34 +03:00

211 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Build Player Files - DigiServer v2{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
<a href="{{ url_for('admin.admin_panel') }}" class="back-link">← Back to Admin Panel</a>
<h1>🧰 Build Player Files for Deployment</h1>
<p style="color: #6c757d; margin-top: 6px;">
Pull the latest player source from a repository onto this server and bake the
configuration it needs to talk to this server. SSH deployments ship exactly
this staged copy, so the version you build here is what players run.
</p>
</div>
<!-- Current staged code status -->
<div class="card status-card">
<h2>Current Staged Player Code</h2>
{% if code_status.available %}
<p><span class="badge badge-success">✅ Ready</span></p>
<ul style="line-height: 1.8;">
<li><strong>Version (git):</strong> <code>{{ code_status.version }}</code></li>
<li><strong>Size:</strong> {{ code_status.size }}</li>
{% if code_status.updated_str %}
<li><strong>Last updated:</strong> {{ code_status.updated_str }}</li>
{% endif %}
<li><strong>Path:</strong> <code>{{ code_status.path }}</code></li>
</ul>
{% else %}
<p>
<span class="badge badge-warning">⚠️ Not staged</span>
{{ code_status.reason }}
</p>
<p style="color: #6c757d;">Path: <code>{{ code_status.path }}</code></p>
{% endif %}
{% if settings.built_at %}
<p style="color: #6c757d; margin-top: 8px;">
Last build saved: {{ settings.built_at }}
{% if settings.built_by %}by {{ settings.built_by }}{% endif %}
</p>
{% endif %}
</div>
<!-- Live build progress (updated by polling below) -->
<div class="card" id="build-progress" style="display: none;">
<h2>Build progress</h2>
<p id="build-progress-text" style="margin: 0;">
<span class="badge badge-warning" id="build-progress-badge">⏳ Running</span>
<span id="build-progress-step"></span>
</p>
<p id="build-progress-message" style="color: #6c757d; margin-top: 8px;"></p>
<div style="margin-top: 10px;">
<button type="button" class="btn btn-secondary" onclick="window.location.reload()">
🔄 Refresh page
</button>
</div>
<p style="color: #6c757d; font-size: 13px; margin-top: 10px;">
The clone takes a couple of minutes. You can leave this page and come back.
</p>
</div>
<form method="POST" action="{{ url_for('admin.build_player_action') }}">
<!-- Repository -->
<div class="card">
<h2>1. Player Files Repository</h2>
<div class="form-group">
<label for="repo_url">Git Repository URL</label>
<input type="text" id="repo_url" name="repo_url" class="form-control"
value="{{ settings.repo_url }}"
placeholder="https://gitea.example.com/org/Kiwy-Signage.git">
<small style="color: #6c757d;">Cloned/refreshed into the staged directory on this server.</small>
</div>
<div class="form-group">
<label for="branch">Branch</label>
<input type="text" id="branch" name="branch" class="form-control"
value="{{ settings.branch }}" placeholder="main">
</div>
</div>
<!-- Server configuration -->
<div class="card">
<h2>2. Player → Server Configuration</h2>
<p style="color: #6c757d;">
The player contacts the DigiServer API directly at
<code>{scheme}://{server}:{port}/api/...</code> (no <code>/digiserver</code> path).
Enter the address players can reach this server on.
</p>
<div class="form-group">
<label for="server_ip">Server IP / Domain</label>
<input type="text" id="server_ip" name="server_ip" class="form-control"
value="{{ settings.server_ip }}" placeholder="signage.example.com or 192.168.0.50">
</div>
<div class="form-group">
<label for="port">Port</label>
<input type="number" id="port" name="port" class="form-control"
value="{{ settings.port }}" min="1" max="65535">
<small style="color: #6c757d;">Use 443 for HTTPS, 80 for plain HTTP, or your custom port (e.g. 8080).</small>
</div>
<div class="form-group">
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
<input type="checkbox" name="use_https" {% if settings.use_https %}checked{% endif %}>
Use HTTPS
</label>
</div>
<div class="form-group">
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
<input type="checkbox" name="verify_ssl" {% if settings.verify_ssl %}checked{% endif %}>
Verify SSL certificate
</label>
<small style="color: #6c757d;">Leave off for self-signed certificates.</small>
</div>
<div class="form-group">
<label for="orientation">Orientation</label>
<select id="orientation" name="orientation" class="form-control">
<option value="Landscape" {% if settings.orientation == 'Landscape' %}selected{% endif %}>Landscape</option>
<option value="Portrait" {% if settings.orientation == 'Portrait' %}selected{% endif %}>Portrait</option>
</select>
</div>
<div class="form-group">
<label for="max_resolution">Max Resolution</label>
<input type="text" id="max_resolution" name="max_resolution" class="form-control"
value="{{ settings.max_resolution }}" placeholder="1920x1080">
</div>
<p style="color: #6c757d; font-size: 13px;">
️ The per-player <strong>screen name</strong> and <strong>quick-connect code</strong>
are filled in automatically for each device during SSH deployment.
</p>
</div>
<!-- Actions -->
<div class="card">
<h2>3. Build</h2>
<div class="card-actions" style="display: flex; gap: 10px; flex-wrap: wrap;">
<button type="submit" name="action" value="build_and_config"
class="btn btn-primary" id="btn-build-all">
⬇️ Build files &amp; write config
</button>
<button type="submit" name="action" value="build_files"
class="btn btn-secondary" id="btn-build-files">
Build files only
</button>
<button type="submit" name="action" value="save_config" class="btn btn-secondary">
Write config only
</button>
</div>
</div>
</form>
</div>
<script>
// Poll the build status so the admin sees live progress instead of a request
// that appears to hang (the clone takes ~1-2 minutes).
(function () {
const statusUrl = "{{ url_for('admin.build_player_status') }}";
const panel = document.getElementById('build-progress');
const badge = document.getElementById('build-progress-badge');
const step = document.getElementById('build-progress-step');
const message = document.getElementById('build-progress-message');
const bAll = document.getElementById('btn-build-all');
const bFiles = document.getElementById('btn-build-files');
let sawRunning = false;
function render(s) {
const state = s.state || 'idle';
if (state === 'running') {
sawRunning = true;
panel.style.display = 'block';
badge.className = 'badge badge-warning';
badge.textContent = '⏳ Running';
step.textContent = s.step || '';
message.textContent = '';
if (bAll) { bAll.disabled = true; bAll.textContent = '⏳ Building…'; }
if (bFiles) { bFiles.disabled = true; }
return;
}
// Reached a terminal state.
if (state === 'success' || state === 'error') {
panel.style.display = 'block';
if (state === 'success') {
badge.className = 'badge badge-success';
badge.textContent = '✅ Build complete';
} else {
badge.className = 'badge badge-danger';
badge.textContent = '❌ Build failed';
}
step.textContent = '';
message.textContent = s.message || '';
if (sawRunning) {
// Reload once so the staged-version panel reflects the new build.
setTimeout(function () { window.location.reload(); }, 1500);
}
}
}
function poll() {
fetch(statusUrl, { headers: { 'Accept': 'application/json' }, cache: 'no-store' })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (s) { if (s) render(s); })
.catch(function () { /* transient — keep polling */ });
}
poll();
setInterval(poll, 3000);
})();
</script>
{% endblock %}