147 lines
8.3 KiB
HTML
147 lines
8.3 KiB
HTML
{% extends "layout.html" %}
|
|
|
|
{% block title %}Global Landing Page Registry - BZOD Admin{% endblock %}
|
|
|
|
{% block active_pages %}active{% endblock %}
|
|
|
|
{% block header_title %}Global Landing Page Registry{% endblock %}
|
|
|
|
{% block content %}
|
|
{% if let Some(err) = error %}
|
|
<div class="alert alert-error">
|
|
{{ err }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="card registered-links-shell" style="padding: 0; overflow: hidden;">
|
|
<div class="registered-links-header">
|
|
<h3 style="font-size: 1.1rem; display: flex; align-items: center; gap: 0.5rem;">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
Global Landing Page Registry
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="table-container">
|
|
<table class="registered-pages-table">
|
|
<colgroup>
|
|
<col class="col-page-title" style="width: 25%;">
|
|
<col class="col-page-paths" style="width: 25%;">
|
|
<col class="col-owner" style="width: 15%;">
|
|
<col class="col-page-status" style="width: 10%;">
|
|
<col class="col-page-qr" style="width: 8%;">
|
|
<col class="col-page-actions" style="width: 17%;">
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th>Page</th>
|
|
<th>Paths</th>
|
|
<th>Owner / Tenant</th>
|
|
<th>Status</th>
|
|
<th>QR Code</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% if pages.is_empty() %}
|
|
<tr>
|
|
<td colspan="6" style="text-align: center; color: var(--text-secondary); padding: 3rem;">
|
|
No landing pages registered across tenants.
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
{% for row in pages %}
|
|
<tr>
|
|
<td data-label="Page">
|
|
<div class="page-title-block">
|
|
<div class="page-title-heading">{{ row.page.title }}</div>
|
|
<div class="page-title-meta">UUID: {{ row.page.id[0..8] }}...</div>
|
|
<div class="page-title-meta">Created {{ row.page.created_at[0..10] }}</div>
|
|
</div>
|
|
</td>
|
|
<td data-label="Paths">
|
|
<div class="page-paths">
|
|
<div class="page-path-group">
|
|
<span class="page-path-caption">Short Path</span>
|
|
<a href="/p/{{ row.page.code }}" target="_blank" class="page-path-link">
|
|
/p/{{ row.page.code }}
|
|
</a>
|
|
</div>
|
|
<div class="page-path-group">
|
|
<span class="page-path-caption">SEO Preview Path</span>
|
|
<a href="/p/{{ row.page.code }}/{{ row.page.slug }}" target="_blank" class="page-path-link secondary">
|
|
/p/{{ row.page.code }}/{{ row.page.slug }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td data-label="Owner / Tenant">
|
|
<div>
|
|
{% if let Some(u) = row.owner_username.as_deref() %}
|
|
<strong style="color: var(--text-primary);">{{ u }}</strong>
|
|
{% else %}
|
|
<span class="text-muted">Unassigned</span>
|
|
{% endif %}
|
|
<div style="font-family: monospace; font-size: 0.72rem; color: var(--text-muted);">{{ row.owner_tenant_id }}</div>
|
|
</div>
|
|
</td>
|
|
<td data-label="Status" class="status-cell">
|
|
<span class="badge badge-{{ row.page.state }}">
|
|
{{ row.page.state }}
|
|
</span>
|
|
</td>
|
|
{% let code = row.page.code.as_str() %}
|
|
{% include "components/qr_preview.html" %}
|
|
<td data-label="Actions" class="actions-cell">
|
|
<div class="action-stack" style="display: flex; gap: 0.35rem; flex-wrap: wrap;">
|
|
<a href="/admin/moderation" class="btn btn-secondary" style="padding: 0.3rem 0.5rem; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 0.2rem;">
|
|
🛡️ Moderate
|
|
</a>
|
|
<a href="/admin/slugs" class="btn btn-secondary" style="padding: 0.3rem 0.5rem; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 0.2rem;">
|
|
🔄 Transfer
|
|
</a>
|
|
<a href="/admin/analytics/page/{{ row.page.id }}" class="btn btn-secondary" style="padding: 0.3rem 0.5rem; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 0.2rem;">
|
|
📊 Analytics
|
|
</a>
|
|
<form action="/admin/pages/delete/{{ row.page.id }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this page?');" style="display: inline;">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<button type="submit" class="btn btn-danger" style="padding: 0.3rem 0.5rem; font-size: 0.75rem;">
|
|
Delete
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="pagination">
|
|
{% if current_page > 1 %}
|
|
<a href="/admin/pages?page=1" class="btn btn-secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;"><< First</a>
|
|
<a href="/admin/pages?page={{ current_page - 1 }}" class="btn btn-secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;">< Prev</a>
|
|
{% else %}
|
|
<span class="btn btn-secondary" style="opacity: 0.5; cursor: not-allowed; padding: 0.4rem 0.8rem; font-size: 0.85rem;"><< First</span>
|
|
<span class="btn btn-secondary" style="opacity: 0.5; cursor: not-allowed; padding: 0.4rem 0.8rem; font-size: 0.85rem;">< Prev</span>
|
|
{% endif %}
|
|
|
|
{% for p in visible_pages %}
|
|
{% if self.is_current(p) %}
|
|
<span class="btn btn-primary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem; font-weight: bold;">[{{ p }}]</span>
|
|
{% else %}
|
|
<a href="/admin/pages?page={{ p }}" class="btn btn-secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;">{{ p }}</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if current_page < total_pages %}
|
|
<a href="/admin/pages?page={{ current_page + 1 }}" class="btn btn-secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;">Next ></a>
|
|
<a href="/admin/pages?page={{ total_pages }}" class="btn btn-secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;">Last >></a>
|
|
{% else %}
|
|
<span class="btn btn-secondary" style="opacity: 0.5; cursor: not-allowed; padding: 0.4rem 0.8rem; font-size: 0.85rem;">Next ></span>
|
|
<span class="btn btn-secondary" style="opacity: 0.5; cursor: not-allowed; padding: 0.4rem 0.8rem; font-size: 0.85rem;">Last >></span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|