Files
GuacPanel/webgui/templates/guacamole.html
T
njomac 50c125e0db Initial commit — GuacPanel v1.0
All-in-one installer za Apache Guacamole s Nginx reverse proxy,
fail2ban, SSL (Let's Encrypt / Self-signed), GeoIP blokiranjem
i Flask web GUI za upravljanje.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 11:21:44 +02:00

133 lines
4.0 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 %}Kontejneri Guacamole Manager{% endblock %}
{% block content %}
<h4 class="mb-4"><i class="bi bi-boxes me-2"></i>Docker kontejneri</h4>
<!-- Status kartice -->
<div class="row g-3 mb-4">
{% for name, running in containers.items() %}
<div class="col-md-4">
<div class="card p-3">
<div class="d-flex align-items-center gap-3">
<span class="status-dot {{ 'status-ok' if running else 'status-err' }}"></span>
<div>
<div class="fw-semibold">{{ name }}</div>
<small class="{{ 'text-success' if running else 'text-danger' }}">
{{ 'Aktivan' if running else 'Nije aktivan' }}
</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- Akcije -->
<div class="card mb-4">
<div class="card-header fw-semibold">Upravljanje</div>
<div class="card-body d-flex gap-2 flex-wrap">
<button class="btn btn-success" onclick="containerAction('start')">
<i class="bi bi-play-fill"></i> Start
</button>
<button class="btn btn-warning" onclick="containerAction('restart')">
<i class="bi bi-arrow-clockwise"></i> Restart
</button>
<button class="btn btn-danger" onclick="containerAction('stop')">
<i class="bi bi-stop-fill"></i> Stop
</button>
<div class="ms-auto">
<select id="log-source" class="form-select form-select-sm d-inline-block w-auto"
onchange="switchLog(this.value)">
<option value="guacamole">guacamole</option>
<option value="guacd">guacd</option>
<option value="postgres">postgres</option>
<option value="nginx">nginx access</option>
<option value="nginx-error">nginx error</option>
<option value="fail2ban">fail2ban</option>
</select>
<button class="btn btn-sm btn-outline-secondary ms-1" onclick="toggleLog()">
<i class="bi bi-terminal" id="log-icon"></i>
<span id="log-btn-txt">Log</span>
</button>
</div>
</div>
</div>
<!-- Live log -->
<div id="log-panel" class="card d-none">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="fw-semibold">
<i class="bi bi-terminal me-1"></i>
Live log: <span id="log-title">guacamole</span>
</span>
<button class="btn btn-sm btn-outline-secondary" onclick="clearLog()">
<i class="bi bi-trash"></i> Očisti
</button>
</div>
<div id="log-output"></div>
</div>
{% endblock %}
{% block scripts %}
<script>
let logSource = null;
let logVisible = false;
async function containerAction(action) {
const btn = event.target.closest('button');
const orig = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = `<span class="spinner-border spinner-border-sm"></span> ${action}...`;
const r = await api(`/api/guacamole/${action}`);
showToast(r.ok ? `${action} izvršen` : r.msg, r.ok);
btn.disabled = false;
btn.innerHTML = orig;
if (r.ok) setTimeout(() => location.reload(), 2000);
}
function switchLog(service) {
if (logVisible) {
stopLog();
startLog(service);
}
document.getElementById('log-title').textContent = service;
}
function toggleLog() {
if (logVisible) {
stopLog();
logVisible = false;
document.getElementById('log-panel').classList.add('d-none');
document.getElementById('log-btn-txt').textContent = 'Log';
} else {
logVisible = true;
document.getElementById('log-panel').classList.remove('d-none');
document.getElementById('log-btn-txt').textContent = 'Zatvori';
startLog(document.getElementById('log-source').value);
}
}
function startLog(service) {
stopLog();
const out = document.getElementById('log-output');
logSource = new EventSource(`/api/logs/${service}`);
logSource.onmessage = e => {
const line = document.createElement('div');
line.textContent = JSON.parse(e.data);
out.appendChild(line);
out.scrollTop = out.scrollHeight;
};
}
function stopLog() {
if (logSource) { logSource.close(); logSource = null; }
}
function clearLog() {
document.getElementById('log-output').innerHTML = '';
}
</script>
{% endblock %}