changes
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Audit log</h1>
|
||||
<div class="text-muted">Last logs (limit 200).</div>
|
||||
<div class="text-muted">Last logs (limit 200)</div>
|
||||
</div>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.index') }}"><i class="fa-solid fa-arrow-left me-1"></i>Back</a>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Admin panel</h1>
|
||||
<div class="text-muted">Administrative tools and system overview.</div>
|
||||
<div class="text-muted">Administrative tools and system overview</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.users') }}"><i class="fa-solid fa-users me-1"></i>Users</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">SMTP</h1>
|
||||
<div class="text-muted">Test email sending configuration.</div>
|
||||
<div class="text-muted">Test email sending configuration</div>
|
||||
</div>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.index') }}"><i class="fa-solid fa-arrow-left me-1"></i>Back</a>
|
||||
</div>
|
||||
@@ -30,12 +30,12 @@
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-gear me-2"></i>Wymagane zmienne</div>
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-gear me-2"></i>Variables</div>
|
||||
<ul class="small mb-0">
|
||||
<li><code>SMTP_HOST</code>, <code>SMTP_PORT</code></li>
|
||||
<li><code>SMTP_FROM</code></li>
|
||||
<li>opcjonalnie: <code>SMTP_USER</code>, <code>SMTP_PASS</code></li>
|
||||
<li>opcjonalnie: <code>SMTP_USE_TLS</code> / <code>SMTP_USE_SSL</code></li>
|
||||
<li>optional: <code>SMTP_USER</code>, <code>SMTP_PASS</code></li>
|
||||
<li>optional: <code>SMTP_USE_TLS</code> / <code>SMTP_USE_SSL</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Users</h1>
|
||||
<div class="text-muted">Lista kont w systemie.</div>
|
||||
<div class="text-muted">Accounts</div>
|
||||
</div>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.index') }}"><i class="fa-solid fa-arrow-left me-1"></i>Back</a>
|
||||
</div>
|
||||
@@ -16,9 +16,9 @@
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Email</th>
|
||||
<th>Rola</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Utworzono</th>
|
||||
<th>Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">API</h1>
|
||||
<div class="text-muted">Endpoints overview (UI reference only).</div>
|
||||
<div class="text-muted">Endpoints overview (UI reference only)</div>
|
||||
</div>
|
||||
{% if current_user.is_authenticated %}
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('dashboards.index') }}"><i class="fa-solid fa-arrow-left me-1"></i>Back</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Dashboards</h1>
|
||||
<div class="text-muted">Your monitoring dashboards.</div>
|
||||
<div class="text-muted">Your monitoring dashboards</div>
|
||||
</div>
|
||||
<a class="btn btn-primary" href="{{ url_for('dashboards.new') }}"><i class="fa-solid fa-plus me-1"></i>New dashboard</a>
|
||||
</div>
|
||||
@@ -15,7 +15,13 @@
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold">{{ d.name }}</div>
|
||||
<div class="text-muted small">{{ d.description or '' }}</div>
|
||||
<div class="text-muted small mb-3">{{ d.description or '' }}</div>
|
||||
<div class="d-flex flex-wrap gap-2 small">
|
||||
<span class="badge text-bg-light">{{ d.widgets_count }} widgets</span>
|
||||
<span class="badge text-bg-light">{{ d.devices_count }} devices</span>
|
||||
<span class="badge text-bg-light">{{ d.charts_count }} charts</span>
|
||||
<span class="badge text-bg-light">{{ d.tables_count }} tables</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white border-0 pt-0 pb-3 px-3">
|
||||
<a class="btn btn-outline-primary btn-sm" href="{{ url_for('dashboards.view', dashboard_id=d.id) }}">Open <i class="fa-solid fa-arrow-right ms-1"></i></a>
|
||||
|
||||
@@ -31,13 +31,20 @@ window.MIKROMON = {
|
||||
{% for w in widgets %}
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card shadow-sm h-100">
|
||||
|
||||
<div class="card-header bg-white">
|
||||
<div class="card-header bg-white d-flex align-items-center justify-content-between gap-2 flex-wrap">
|
||||
<div class="fw-semibold">{{ w.title }}</div>
|
||||
{% if w.widget_type != 'table' %}
|
||||
<select class="form-select form-select-sm" data-range-widget="{{ w.id }}" style="width:auto">
|
||||
<option value="1m">1m</option>
|
||||
<option value="10m">10m</option>
|
||||
<option value="1h" selected>1h</option>
|
||||
<option value="3h">3h</option>
|
||||
<option value="10h">10h</option>
|
||||
</select>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
{% if w.widget_type == 'table' %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm align-middle mb-0" data-table-widget="{{ w.id }}">
|
||||
@@ -46,7 +53,7 @@ window.MIKROMON = {
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="chart-wrap">
|
||||
<div class="chart-wrap" style="height: {{ w.height_px or 260 }}px;">
|
||||
<canvas id="chart-{{ w.id }}"></canvas>
|
||||
</div>
|
||||
<div class="text-muted small mt-2" id="meta-{{ w.id }}">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-user-plus me-2"></i>Share with user</div>
|
||||
<form method="post" action="{{ url_for('dashboards.share_post', dashboard_id=dashboard.id) }}">
|
||||
<form method="post" action="{{ url_for('dashboards.share_add', dashboard_id=dashboard.id) }}">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="row g-2">
|
||||
<div class="col-12 col-md-7">{{ form.email(class_="form-control", placeholder="email@example.com") }}</div>
|
||||
@@ -46,18 +46,21 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-link me-2"></i>Public link</div>
|
||||
{% if public %}
|
||||
{% if public_link %}
|
||||
<div class="alert alert-success small">
|
||||
<a href="{{ url_for('dashboards.public_view', token=public.token) }}" target="_blank">{{ url_for('dashboards.public_view', token=public.token, _external=true) }}</a>
|
||||
<a href="{{ url_for('dashboards.public_view', token=public_link.token) }}" target="_blank">{{ url_for('dashboards.public_view', token=public_link.token, _external=true) }}</a>
|
||||
</div>
|
||||
<form method="post" action="{{ url_for('dashboards.public_link_delete', dashboard_id=dashboard.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-outline-danger" type="submit"><i class="fa-solid fa-trash me-1"></i>Delete link</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="alert alert-secondary small">No active public link.</div>
|
||||
<form method="post" action="{{ url_for('dashboards.public_link_create', dashboard_id=dashboard.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-outline-primary" type="submit"><i class="fa-solid fa-link me-1"></i>Create link</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{{ url_for('dashboards.share_public', dashboard_id=dashboard.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-outline-primary" type="submit"><i class="fa-solid fa-rotate me-1"></i>Create / refresh</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,12 +19,23 @@
|
||||
{% for w in widgets %}
|
||||
<div class="col-12 col-lg-{{ w.col_span or 6 }}">
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-header bg-white d-flex align-items-center justify-content-between">
|
||||
<div class="card-header bg-white d-flex align-items-center justify-content-between gap-2 flex-wrap">
|
||||
<div class="fw-semibold">{{ w.title }}</div>
|
||||
<form method="post" action="{{ url_for('dashboards.widget_delete', dashboard_id=dashboard.id, widget_id=w.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-sm btn-outline-danger" type="submit" title="Delete"><i class="fa-solid fa-trash"></i></button>
|
||||
</form>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
{% if w.widget_type != 'table' %}
|
||||
<select class="form-select form-select-sm" data-range-widget="{{ w.id }}" style="width:auto">
|
||||
<option value="1m">1m</option>
|
||||
<option value="10m">10m</option>
|
||||
<option value="1h" selected>1h</option>
|
||||
<option value="3h">3h</option>
|
||||
<option value="10h">10h</option>
|
||||
</select>
|
||||
{% endif %}
|
||||
<form method="post" action="{{ url_for('dashboards.widget_delete', dashboard_id=dashboard.id, widget_id=w.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-sm btn-outline-danger" type="submit" title="Delete"><i class="fa-solid fa-trash"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if w.widget_type == 'table' %}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<select class="form-select" id="itemSelect">
|
||||
<option value="">— select —</option>
|
||||
</select>
|
||||
<div class="form-text">E.g. interface / queue (depends on preset).</div>
|
||||
<div class="form-text" id="itemHelp">E.g. interface / queue (depends on preset).</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
@@ -91,6 +91,7 @@
|
||||
const itemWrap = document.getElementById('itemWrap');
|
||||
const itemSelect = document.getElementById('itemSelect');
|
||||
const itemLabel = document.getElementById('itemLabel');
|
||||
const itemHelp = document.getElementById('itemHelp');
|
||||
|
||||
function presetNeedsItem(p){
|
||||
if(!p) return false;
|
||||
@@ -109,7 +110,8 @@
|
||||
}
|
||||
|
||||
itemWrap.classList.remove('d-none');
|
||||
itemLabel.textContent = String(presetKey).includes('queue') ? 'Queue' : 'Interface / item';
|
||||
itemLabel.textContent = p.item_label || (String(presetKey).includes('queue') ? 'Queue' : 'Interface / item');
|
||||
itemHelp.textContent = p.item_help || 'E.g. interface / queue / metric (depends on preset).';
|
||||
itemSelect.innerHTML = '<option value="">Loading…</option>';
|
||||
|
||||
try{
|
||||
|
||||
@@ -26,11 +26,15 @@
|
||||
{{ form.host(class_="form-control") }}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">REST port</label>
|
||||
{{ form.rest_port(class_="form-control") }}
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">Protocol</label>
|
||||
{{ form.rest_scheme(class_="form-select", id="restScheme") }}
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">REST port</label>
|
||||
{{ form.rest_port(class_="form-control", id="restPort") }}
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">REST base path</label>
|
||||
{{ form.rest_base_path(class_="form-control") }}
|
||||
</div>
|
||||
@@ -45,24 +49,12 @@
|
||||
<div class="form-text">Leave blank to keep the current password.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="col-12" id="tlsRow">
|
||||
<div class="form-check">
|
||||
{{ form.allow_insecure_tls(class_="form-check-input") }}
|
||||
<label class="form-check-label">Allow insecure TLS (self-signed)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
{{ form.ssh_enabled(class_="form-check-input", id="sshEnabled") }}
|
||||
<label class="form-check-label" for="sshEnabled">Enable SSH connector</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">SSH port</label>
|
||||
{{ form.ssh_port(class_="form-control") }}
|
||||
<div class="form-text">Used only when SSH is enabled.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
@@ -78,10 +70,22 @@
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-circle-info me-2"></i>Notes</div>
|
||||
<ul class="small mb-0">
|
||||
<li>Changing credentials updates the encrypted secret stored in the database.</li>
|
||||
<li>If REST fails, verify host/port/path and TLS setting.</li>
|
||||
<li>For HTTP, TLS options are ignored.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const scheme=document.getElementById('restScheme');
|
||||
const tlsRow=document.getElementById('tlsRow');
|
||||
function sync(){
|
||||
tlsRow.style.display=((scheme.value||'https')==='https')?'':'none';
|
||||
}
|
||||
scheme.addEventListener('change', sync);
|
||||
sync();
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Devices</h1>
|
||||
<div class="text-muted">Routers / hosts to monitor.</div>
|
||||
<div class="text-muted">Routers / hosts to monitor</div>
|
||||
</div>
|
||||
<a class="btn btn-primary" href="{{ url_for('devices.new') }}"><i class="fa-solid fa-plus me-1"></i>Add device</a>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0">Add device</h1>
|
||||
<div class="text-muted">Configure REST/SSH access.</div>
|
||||
<div class="text-muted">Configure RouterOS REST access</div>
|
||||
</div>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('devices.index') }}"><i class="fa-solid fa-arrow-left me-1"></i>Back</a>
|
||||
</div>
|
||||
@@ -26,11 +26,15 @@
|
||||
{{ form.host(class_="form-control", placeholder="192.168.1.1 or router.example.com") }}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">REST port</label>
|
||||
{{ form.rest_port(class_="form-control") }}
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">Protocol</label>
|
||||
{{ form.rest_scheme(class_="form-select", id="restScheme") }}
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">REST port</label>
|
||||
{{ form.rest_port(class_="form-control", id="restPort") }}
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label">REST base path</label>
|
||||
{{ form.rest_base_path(class_="form-control", placeholder="/rest") }}
|
||||
</div>
|
||||
@@ -44,24 +48,12 @@
|
||||
{{ form.password(class_="form-control", placeholder="••••••••") }}
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="col-12" id="tlsRow">
|
||||
<div class="form-check">
|
||||
{{ form.allow_insecure_tls(class_="form-check-input") }}
|
||||
<label class="form-check-label">Allow insecure TLS (self-signed)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
{{ form.ssh_enabled(class_="form-check-input", id="sshEnabled") }}
|
||||
<label class="form-check-label" for="sshEnabled">Enable SSH connector</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">SSH port</label>
|
||||
{{ form.ssh_port(class_="form-control") }}
|
||||
<div class="form-text">Used only when SSH is enabled.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
@@ -76,12 +68,31 @@
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold mb-2"><i class="fa-solid fa-circle-info me-2"></i>Tips</div>
|
||||
<ul class="small mb-0">
|
||||
<li>REST uses the MikroTik API (<code>/rest</code>).</li>
|
||||
<li>If you use a self-signed cert, enable insecure TLS.</li>
|
||||
<li>SSH is optional (e.g. for commands/reads).</li>
|
||||
<li>Use HTTPS for encrypted RouterOS REST.</li>
|
||||
<li>Use HTTP only for local trusted networks when needed.</li>
|
||||
<li>Default path is <code>/rest</code>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const scheme=document.getElementById('restScheme');
|
||||
const port=document.getElementById('restPort');
|
||||
const tlsRow=document.getElementById('tlsRow');
|
||||
function sync(){
|
||||
const isHttps=(scheme.value||'https')==='https';
|
||||
tlsRow.style.display=isHttps?'':'none';
|
||||
if(!port.value || port.dataset.autofill==='1'){
|
||||
port.value=isHttps?'443':'80';
|
||||
port.dataset.autofill='1';
|
||||
}
|
||||
}
|
||||
port.addEventListener('input', ()=>{ port.dataset.autofill='0'; });
|
||||
scheme.addEventListener('change', sync);
|
||||
sync();
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body style="font-family:Arial,Helvetica,sans-serif;line-height:1.4">
|
||||
<h2 style="margin:0 0 12px 0">MikroMon — password reset</h2>
|
||||
<p>We received a request to reset your password.</p>
|
||||
<p>We received a request to reset your password</p>
|
||||
<p><a href="{{ reset_url }}" style="display:inline-block;padding:10px 14px;background:#0d6efd;color:#fff;text-decoration:none;border-radius:6px">Set a new password</a></p>
|
||||
<p style="color:#666;font-size:12px">This link expires in {{ ttl_minutes }} minutes. If this wasn't you, ignore this email.</p>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user