04/30 Web Checker web app ver. 1.0

This commit is contained in:
2026-04-30 17:15:56 -04:00
parent feb8e5051c
commit cd63d5a020
39 changed files with 8031 additions and 1 deletions
+176
View File
@@ -0,0 +1,176 @@
{% extends "base.html" %}
{% block title %}Websites — Website Checker{% endblock %}
{% block content %}
<div class="page-header">
<h1 class="page-title">Website Link Management</h1>
<button class="btn btn-primary" onclick="openModal('modal-create-site')"> Add Website</button>
</div>
<div class="card">
<table class="table table-hover">
<thead>
<tr><th>ID</th><th>Name</th><th>Type</th><th>URL</th><th>Note</th><th>Visibility</th><th>Created By</th><th>Actions</th></tr>
</thead>
<tbody>
{% for w in websites %}
<tr class="{{ 'row-weekly' if w.check_type == 'weekly' else '' }}">
<td>{{ w.id }}</td>
<td><strong>{{ w.name }}</strong></td>
<td><span class="badge badge-{{ 'warn' if w.check_type == 'weekly' else 'neutral' }}">{{ w.check_type }}</span></td>
<td class="url-cell"><a href="{{ w.url }}" target="_blank" rel="noopener">{{ w.url[:60] }}{% if w.url|length > 60 %}…{% endif %}</a></td>
<td class="text-muted">{{ (w.note or '')[:40] }}{% if (w.note or '')|length > 40 %}…{% endif %}</td>
<td><span class="badge badge-{{ 'accent' if w.visibility == 'assigned' else 'neutral' }}">{{ w.visibility }}</span></td>
<td class="text-muted">{{ w.creator or '—' }}</td>
<td class="actions">
<button class="btn btn-ghost btn-sm" onclick="loadEditSite({{ w.id }})">✎ Edit</button>
<form method="post" action="{{ url_for('admin_websites.delete', website_id=w.id) }}"
style="display:inline" onsubmit="return confirm('Soft-delete {{ w.name }}?')">
<button class="btn btn-danger btn-sm" type="submit"></button>
</form>
</td>
</tr>
{% else %}
<tr><td colspan="8" class="text-center text-muted">No websites configured.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Create Website Modal -->
<div class="modal-overlay" id="modal-create-site">
<div class="modal-dialog modal-lg">
<div class="modal-header">
<h3>Add Website</h3>
<button class="modal-close" onclick="closeModal('modal-create-site')"></button>
</div>
<form method="post" action="{{ url_for('admin_websites.create') }}">
<div class="modal-body">
<div class="form-row">
<div class="form-group flex-1">
<label class="form-label">Name *</label>
<input class="form-control" name="name" required>
</div>
<div class="form-group flex-1">
<label class="form-label">Check Type</label>
<select class="form-control" name="check_type">
<option value="daily">📅 Daily</option>
<option value="weekly">🗓 Weekly</option>
</select>
</div>
</div>
<div class="form-group">
<label class="form-label">URL *</label>
<input class="form-control" name="url" type="url" required>
</div>
<div class="form-group">
<label class="form-label">Visibility</label>
<select class="form-control" name="visibility">
<option value="all">All users</option>
<option value="assigned">Assigned users only</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Note</label>
<textarea class="form-control" name="note" rows="2"></textarea>
</div>
<hr>
<h4 style="margin-bottom:.5rem">Credentials <button type="button" class="btn btn-secondary btn-sm" onclick="addCredRow(this)"> Add</button></h4>
<div class="cred-rows">
<div class="cred-row">
<div class="form-group"><label class="form-label">Label</label><input class="form-control" name="cred_label[]" placeholder="e.g. Admin"></div>
<div class="form-group"><label class="form-label">Username</label><input class="form-control" name="cred_username[]"></div>
<div class="form-group"><label class="form-label">Password</label><input class="form-control" name="cred_password[]" type="password"></div>
<div class="form-group"><label class="form-label">&nbsp;</label><button type="button" class="btn btn-danger btn-sm" onclick="removeRow(this)"></button></div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-ghost" onclick="closeModal('modal-create-site')">Cancel</button>
<button type="submit" class="btn btn-primary">Create Website</button>
</div>
</form>
</div>
</div>
<!-- Edit Website Modal -->
<div class="modal-overlay" id="modal-edit-site">
<div class="modal-dialog modal-lg">
<div class="modal-header">
<h3>Edit Website</h3>
<button class="modal-close" onclick="closeModal('modal-edit-site')"></button>
</div>
<form method="post" id="edit-site-form">
<div class="modal-body" id="edit-site-body">
<div class="text-center text-muted">Loading…</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-ghost" onclick="closeModal('modal-edit-site')">Cancel</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
<script>
function loadEditSite(id) {
fetch('/admin/websites/' + id + '/detail')
.then(r => r.json())
.then(site => {
const form = document.getElementById('edit-site-form');
form.action = '/admin/websites/' + id + '/edit';
document.getElementById('edit-site-body').innerHTML = buildSiteForm(site);
openModal('modal-edit-site');
});
}
function buildSiteForm(s) {
const creds = (s.credentials || []).map(c => `
<div class="cred-row">
<input class="form-control" name="cred_label[]" placeholder="Label" value="${esc(c.label)}">
<input class="form-control" name="cred_username[]" placeholder="Username" value="${esc(c.username)}">
<input class="form-control" name="cred_password[]" placeholder="Password" type="password" value="${esc(c.password)}">
<button type="button" class="btn btn-danger btn-sm" onclick="removeRow(this)">✕</button>
</div>`).join('') || emptyCredRow();
return `
<div class="form-group"><label class="form-label">Name *</label>
<input class="form-control" name="name" value="${esc(s.name)}" required></div>
<div class="form-row">
<div class="form-group flex-1"><label class="form-label">Check Type</label>
<select class="form-control" name="check_type">
<option value="daily" ${s.check_type==='daily'?'selected':''}>📅 Daily</option>
<option value="weekly" ${s.check_type==='weekly'?'selected':''}>🗓 Weekly</option>
</select></div>
<div class="form-group flex-1"><label class="form-label">Visibility</label>
<select class="form-control" name="visibility">
<option value="all" ${s.visibility==='all'?'selected':''}>All users</option>
<option value="assigned" ${s.visibility==='assigned'?'selected':''}>Assigned only</option>
</select></div>
</div>
<div class="form-group"><label class="form-label">URL *</label>
<input class="form-control" name="url" type="url" value="${esc(s.url)}" required></div>
<div class="form-group"><label class="form-label">Note</label>
<textarea class="form-control" name="note" rows="2">${esc(s.note)}</textarea></div>
<hr>
<h4>Credentials <button type="button" class="btn btn-ghost btn-sm" onclick="addCredRow(this)"> Add</button></h4>
<div class="cred-rows">${creds}</div>`;
}
function emptyCredRow() {
return `<div class="cred-row">
<input class="form-control" name="cred_label[]" placeholder="Label">
<input class="form-control" name="cred_username[]" placeholder="Username">
<input class="form-control" name="cred_password[]" placeholder="Password" type="password">
<button type="button" class="btn btn-danger btn-sm" onclick="removeRow(this)">✕</button>
</div>`;
}
function addCredRow(btn) {
btn.closest('.modal-body').querySelector('.cred-rows').insertAdjacentHTML('beforeend', emptyCredRow());
}
function removeRow(btn) { btn.closest('.cred-row').remove(); }
function esc(s) { return (s||'').replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/</g,'&lt;'); }
</script>
{% endblock %}