first commit
This commit is contained in:
14
app/templates/admin/audit.html
Normal file
14
app/templates/admin/audit.html
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="hero-panel mb-4">
|
||||
<div class="app-section-title mb-0">
|
||||
<span class="feature-icon"><i class="fa-solid fa-clipboard-list"></i></span>
|
||||
<div>
|
||||
<h1 class="h3 mb-0">{{ t('admin.audit') }}</h1>
|
||||
<div class="text-body-secondary">{{ t('admin.audit_subtitle') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card"><div class="card-body"><div class="table-responsive"><table class="table align-middle mb-0"><thead><tr><th>{{ t('common.date') }}</th><th>User</th><th>Action</th><th>Target</th><th>Details</th></tr></thead><tbody>{% for log in logs %}<tr><td>{{ log.created_at.strftime('%Y-%m-%d %H:%M') }}</td><td>{{ log.user.email if log.user else '-' }}</td><td>{{ log.action }}</td><td>{{ log.target_type }} #{{ log.target_id }}</td><td class="small text-body-secondary">{{ log.details }}</td></tr>{% else %}<tr><td colspan="5" class="text-body-secondary">{{ t('stats.no_data') }}</td></tr>{% endfor %}</tbody></table></div></div></div>
|
||||
{% endblock %}
|
||||
23
app/templates/admin/categories.html
Normal file
23
app/templates/admin/categories.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-4">
|
||||
<div class="card shadow-sm"><div class="card-body">
|
||||
<h1 class="h4 mb-3">{{ t('admin.categories') }}</h1>
|
||||
<form method="post">{{ form.hidden_tag() }}
|
||||
<div class="row g-3">
|
||||
<div class="col-12">{{ form.key.label(class='form-label') }}{{ form.key(class='form-control') }}</div>
|
||||
<div class="col-md-6">{{ form.name_pl.label(class='form-label') }}{{ form.name_pl(class='form-control') }}</div>
|
||||
<div class="col-md-6">{{ form.name_en.label(class='form-label') }}{{ form.name_en(class='form-control') }}</div>
|
||||
<div class="col-md-6">{{ form.color.label(class='form-label') }}{{ form.color(class='form-select') }}</div>
|
||||
<div class="col-12">{{ form.submit(class='btn btn-primary w-100') }}</div>
|
||||
</div>
|
||||
</form>
|
||||
</div></div>
|
||||
</div>
|
||||
<div class="col-lg-8"><div class="card shadow-sm"><div class="card-body"><div class="table-responsive"><table class="table">
|
||||
<thead><tr><th>{{ t('common.name') }}</th><th>PL</th><th>EN</th><th>{{ t('common.status') }}</th></tr></thead>
|
||||
<tbody>{% for category in categories %}<tr><td>{{ category.key }}</td><td>{{ category.name_pl }}</td><td>{{ category.name_en }}</td><td>{{ t('common.active') if category.is_active else t('common.inactive') }}</td></tr>{% endfor %}</tbody>
|
||||
</table></div></div></div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
32
app/templates/admin/dashboard.html
Normal file
32
app/templates/admin/dashboard.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="hero-panel mb-4">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3">
|
||||
<div class="app-section-title mb-0">
|
||||
<span class="feature-icon"><i class="fa-solid fa-shield-halved"></i></span>
|
||||
<div>
|
||||
<h1 class="h3 mb-0">{{ t('admin.title') }}</h1>
|
||||
<div class="text-body-secondary">{{ t('admin.subtitle') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<form method="post" action="{{ url_for('admin.run_reports') }}"><button class="btn btn-outline-primary"><i class="fa-solid fa-paper-plane me-2"></i>Run reports</button></form>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.users') }}"><i class="fa-solid fa-users me-2"></i>{{ t('admin.users') }}</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.categories') }}"><i class="fa-solid fa-tags me-2"></i>{{ t('admin.categories') }}</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('admin.settings') }}"><i class="fa-solid fa-gears me-2"></i>{{ t('admin.settings') }}</a>
|
||||
<a class="btn btn-primary" href="{{ url_for('admin.audit') }}"><i class="fa-solid fa-clipboard-list me-2"></i>{{ t('admin.audit') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-stats mb-4">
|
||||
<div class="card metric-card"><div class="d-flex justify-content-between align-items-center"><div><div class="text-body-secondary">{{ t('admin.users') }}</div><div class="fs-3 fw-bold">{{ stats.users }}</div></div><span class="metric-icon"><i class="fa-solid fa-users"></i></span></div></div>
|
||||
<div class="card metric-card"><div class="d-flex justify-content-between align-items-center"><div><div class="text-body-secondary">{{ t('admin.categories') }}</div><div class="fs-3 fw-bold">{{ stats.categories }}</div></div><span class="metric-icon"><i class="fa-solid fa-tags"></i></span></div></div>
|
||||
<div class="card metric-card"><div class="d-flex justify-content-between align-items-center"><div><div class="text-body-secondary">{{ t('admin.audit') }}</div><div class="fs-3 fw-bold">{{ stats.audit_logs }}</div></div><span class="metric-icon"><i class="fa-solid fa-clipboard-list"></i></span></div></div>
|
||||
<div class="card metric-card"><div class="d-flex justify-content-between align-items-center"><div><div class="text-body-secondary">Admins</div><div class="fs-3 fw-bold">{{ stats.admins }}</div></div><span class="metric-icon"><i class="fa-solid fa-user-shield"></i></span></div></div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-6"><div class="card"><div class="card-body"><h2 class="h5 mb-3"><i class="fa-solid fa-server me-2"></i>{{ t('admin.system') }}</h2><div class="small text-body-secondary d-grid gap-2"><div><strong>{{ t('admin.python') }}:</strong> {{ system.python }}</div><div><strong>{{ t('admin.platform') }}:</strong> {{ system.platform }}</div><div><strong>{{ t('admin.environment') }}:</strong> {{ system.flask_env }}</div><div><strong>{{ t('admin.instance_path') }}:</strong> {{ system.instance_path }}</div><div><strong>{{ t('admin.uploads') }}:</strong> {{ system.upload_count }}</div><div><strong>{{ t('admin.previews') }}:</strong> {{ system.preview_count }}</div><div><strong>{{ t('admin.webhook') }}:</strong> {{ t('common.enabled') if system.webhook_enabled else t('common.disabled') }}</div><div><strong>{{ t('admin.scheduler') }}:</strong> {{ t('common.enabled') if system.scheduler_enabled else t('common.disabled') }}</div></div></div></div></div>
|
||||
<div class="col-lg-6"><div class="card"><div class="card-body"><h2 class="h5 mb-3"><i class="fa-solid fa-database me-2"></i>{{ t('admin.database') }}</h2><div class="small text-body-secondary d-grid gap-2"><div><strong>Engine:</strong> {{ db_info.engine }}</div><div><strong>URL:</strong> {{ db_info.url }}</div><div><strong>Version:</strong> {{ db_version }}</div><div><strong>Max upload MB:</strong> {{ system.max_upload_mb }}</div></div></div></div></div>
|
||||
<div class="col-12"><div class="card"><div class="card-body"><div class="d-flex justify-content-between align-items-center mb-3"><h2 class="h5 mb-0"><i class="fa-solid fa-clock-rotate-left me-2"></i>{{ t('admin.audit') }}</h2><a href="{{ url_for('admin.audit') }}" class="btn btn-sm btn-outline-secondary">{{ t('common.view_all') }}</a></div><div class="table-responsive"><table class="table align-middle mb-0"><thead><tr><th>{{ t('common.date') }}</th><th>Action</th><th>Target</th><th>Details</th></tr></thead><tbody>{% for log in recent_logs %}<tr><td>{{ log.created_at.strftime('%Y-%m-%d %H:%M') }}</td><td>{{ log.action }}</td><td>{{ log.target_type }} #{{ log.target_id }}</td><td class="small text-body-secondary">{{ log.details }}</td></tr>{% else %}<tr><td colspan="4" class="text-body-secondary">{{ t('stats.no_data') }}</td></tr>{% endfor %}</tbody></table></div></div></div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
49
app/templates/admin/settings.html
Normal file
49
app/templates/admin/settings.html
Normal file
@@ -0,0 +1,49 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="mx-auto" style="max-width:1080px">
|
||||
<div class="app-section-title mb-4">
|
||||
<span class="feature-icon"><i class="fa-solid fa-gears"></i></span>
|
||||
<div><h1 class="h3 mb-0">{{ t('admin.settings') }}</h1><div class="text-body-secondary">{{ t('admin.settings_subtitle') }}</div></div>
|
||||
</div>
|
||||
<form method="post" class="row g-3 settings-section">
|
||||
<div class="col-12 col-xl-6"><div class="card h-100"><div class="card-body">
|
||||
<h2 class="h5 mb-3">{{ t('admin.section_general') }}</h2>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-8"><label class="form-label">{{ t('admin.company_name') }}</label><input class="form-control" name="company_name" value="{{ values.get('company_name','') }}"></div>
|
||||
<div class="col-md-4"><label class="form-label">{{ t('admin.max_upload_mb') }}</label><input class="form-control" name="max_upload_mb" value="{{ values.get('max_upload_mb','10') }}"></div>
|
||||
<div class="col-12 form-check ms-2"><input class="form-check-input" type="checkbox" name="registration_enabled" {% if values.get('registration_enabled') == 'true' %}checked{% endif %}><label class="form-check-label">{{ t('admin.registration_enabled') }}</label></div>
|
||||
</div>
|
||||
</div></div></div>
|
||||
|
||||
<div class="col-12 col-xl-6"><div class="card h-100"><div class="card-body">
|
||||
<h2 class="h5 mb-3">{{ t('admin.smtp_section') }}</h2>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-8"><label class="form-label">{{ t('admin.smtp_host') }}</label><input class="form-control" name="smtp_host" value="{{ values.get('smtp_host','') }}"></div>
|
||||
<div class="col-md-4"><label class="form-label">{{ t('admin.smtp_port') }}</label><input class="form-control" name="smtp_port" value="{{ values.get('smtp_port','465') }}"></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('admin.smtp_security') }}</label><select class="form-select" name="smtp_security"><option value="plain" {% if values.get('smtp_security')=='plain' %}selected{% endif %}>{{ t('admin.smtp_plain') }}</option><option value="starttls" {% if values.get('smtp_security')=='starttls' %}selected{% endif %}>STARTTLS</option><option value="ssl" {% if values.get('smtp_security')=='ssl' %}selected{% endif %}>SSL/TLS</option></select></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('admin.smtp_sender') }}</label><input class="form-control" name="smtp_sender" value="{{ values.get('smtp_sender','') }}"></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('admin.smtp_username') }}</label><input class="form-control" name="smtp_username" value="{{ values.get('smtp_username','') }}"></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('admin.smtp_password') }}</label><input class="form-control" type="password" name="smtp_password" value="{{ values.get('smtp_password','') }}"></div>
|
||||
</div>
|
||||
</div></div></div>
|
||||
|
||||
<div class="col-12 col-xl-6"><div class="card h-100"><div class="card-body">
|
||||
<h2 class="h5 mb-3">{{ t('admin.section_reports') }}</h2>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 form-check ms-2"><input class="form-check-input" type="checkbox" name="reports_enabled" {% if values.get('reports_enabled','true') == 'true' %}checked{% endif %}><label class="form-check-label">{{ t('admin.reports_enabled') }}</label></div>
|
||||
<div class="col-12 form-check ms-2"><input class="form-check-input" type="checkbox" name="report_scheduler_enabled" {% if values.get('report_scheduler_enabled') == 'true' %}checked{% endif %}><label class="form-check-label">{{ t('admin.enable_scheduler') }}</label></div>
|
||||
<div class="col-12"><div class="form-text">{{ t('admin.reports_hint') }}</div></div>
|
||||
</div>
|
||||
</div></div></div>
|
||||
|
||||
<div class="col-12 col-xl-6"><div class="card h-100"><div class="card-body">
|
||||
<h2 class="h5 mb-3">{{ t('admin.section_integrations') }}</h2>
|
||||
<div class="row g-3">
|
||||
<div class="col-12"><label class="form-label">{{ t('admin.webhook_token') }}</label><input class="form-control" name="webhook_api_token" value="{{ values.get('webhook_api_token','') }}"></div>
|
||||
</div>
|
||||
</div></div></div>
|
||||
|
||||
<div class="col-12"><button class="btn btn-primary"><i class="fa-solid fa-floppy-disk me-2"></i>{{ t('common.save') }}</button></div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
26
app/templates/admin/users.html
Normal file
26
app/templates/admin/users.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="row g-3">
|
||||
<div class="col-xl-4"><div class="card shadow-sm"><div class="card-body">
|
||||
<h1 class="h4 mb-3">{{ t('admin.users') }}</h1>
|
||||
<form method="post">{{ form.hidden_tag() }}
|
||||
<div class="mb-2"><label class="form-label">{{ t('user.full_name') }}</label>{{ form.full_name(class='form-control') }}</div>
|
||||
<div class="mb-2"><label class="form-label">{{ t('user.email') }}</label>{{ form.email(class='form-control') }}</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-md-6"><label class="form-label">{{ t('common.role') }}</label>{{ form.role(class='form-select') }}</div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('preferences.language') }}</label>{{ form.language(class='form-select') }}</div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('preferences.reports') }}</label>{{ form.report_frequency(class='form-select') }}</div>
|
||||
<div class="col-md-6"><label class="form-label">{{ t('preferences.theme') }}</label>{{ form.theme(class='form-select') }}</div>
|
||||
</div>
|
||||
<div class="form-check mt-2">{{ form.is_active_user(class='form-check-input') }} <label class="form-check-label">{{ t('user.active') }}</label></div>
|
||||
<div class="form-check">{{ form.must_change_password(class='form-check-input') }} <label class="form-check-label">{{ t('user.must_change_password') }}</label></div>
|
||||
<button class="btn btn-primary mt-3">{{ t('common.save') }}</button>
|
||||
{% if editing_user %}<a class="btn btn-outline-secondary mt-3" href="{{ url_for('admin.users') }}">{{ t('common.cancel') }}</a>{% endif %}
|
||||
</form>
|
||||
</div></div></div>
|
||||
<div class="col-xl-8"><div class="card shadow-sm"><div class="card-body"><div class="table-responsive"><table class="table align-middle">
|
||||
<thead><tr><th>{{ t('common.name') }}</th><th>{{ t('user.email') }}</th><th>{{ t('common.role') }}</th><th>{{ t('preferences.language') }}</th><th>{{ t('preferences.reports') }}</th><th>{{ t('common.status') }}</th><th></th></tr></thead>
|
||||
<tbody>{% for user in users %}<tr><td>{{ user.full_name }}</td><td>{{ user.email }}</td><td>{{ user.role }}</td><td>{{ user.language }}</td><td>{{ user.report_frequency }}</td><td>{% if user.is_active_user %}<span class="badge text-bg-success">{{ t('common.active') }}</span>{% else %}<span class="badge text-bg-secondary">{{ t('common.inactive') }}</span>{% endif %}{% if user.must_change_password %}<span class="badge text-bg-warning">{{ t('user.must_change_password_short') }}</span>{% endif %}</td><td class="text-end"><a class="btn btn-sm btn-outline-primary" href="{{ url_for('admin.users', edit=user.id) }}"><i class="fa-solid fa-pen-to-square"></i></a><form method="post" action="{{ url_for('admin.toggle_password_change', user_id=user.id) }}" class="d-inline">{{ csrf_token() if csrf_token else '' }}<button class="btn btn-sm btn-outline-secondary">{{ t('common.toggle') }}</button></form></td></tr>{% endfor %}</tbody>
|
||||
</table></div></div></div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user