nordabiz/templates/admin/forum_deleted.html
Maciej Pienczyn 110d971dca
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
feat: migrate prod docs to OVH VPS + UTC→Warsaw timezone in all templates
Production moved from on-prem VM 249 (10.22.68.249) to OVH VPS
(57.128.200.27, inpi-vps-waw01). Updated ALL documentation, slash
commands, memory files, architecture docs, and deploy procedures.

Added |local_time Jinja filter (UTC→Europe/Warsaw) and converted
155 .strftime() calls across 71 templates so timestamps display
in Polish timezone regardless of server timezone.

Also includes: created_by_id tracking, abort import fix, ICS
calendar fix for missing end times, Pros Poland data cleanup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:41:53 +02:00

231 lines
6.5 KiB
HTML

{% extends "base.html" %}
{% block title %}Usunięte Treści Forum - Norda Biznes Partner{% endblock %}
{% block extra_css %}
<style>
.admin-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-xl);
}
.admin-header h1 {
font-size: var(--font-size-3xl);
color: var(--text-primary);
}
.section {
background: var(--surface);
padding: var(--spacing-xl);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-xl);
}
.section h2 {
font-size: var(--font-size-xl);
margin-bottom: var(--spacing-lg);
color: var(--text-primary);
border-bottom: 2px solid var(--border);
padding-bottom: var(--spacing-sm);
}
.deleted-item {
padding: var(--spacing-lg);
border: 1px dashed #fecaca;
border-radius: var(--radius);
background: #fef2f2;
margin-bottom: var(--spacing-md);
}
.deleted-item:last-child {
margin-bottom: 0;
}
.deleted-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--spacing-md);
}
.deleted-meta {
font-size: var(--font-size-sm);
color: var(--text-secondary);
}
.deleted-content {
color: var(--text-primary);
margin-bottom: var(--spacing-md);
}
.deleted-info {
font-size: var(--font-size-sm);
color: #dc2626;
font-style: italic;
}
.btn-restore {
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius);
font-size: var(--font-size-sm);
cursor: pointer;
border: 1px solid #86efac;
background: #dcfce7;
color: #166534;
transition: all 0.2s;
}
.btn-restore:hover {
background: #bbf7d0;
}
.empty-state {
text-align: center;
padding: var(--spacing-xl);
color: var(--text-secondary);
}
.back-link {
margin-bottom: var(--spacing-lg);
}
.back-link a {
color: var(--text-secondary);
text-decoration: none;
}
.back-link a:hover {
color: var(--primary);
}
</style>
{% endblock %}
{% block content %}
<div class="back-link">
<a href="{{ url_for('forum.admin_forum') }}">&larr; Powrót do moderacji forum</a>
</div>
<div class="admin-header">
<h1>Usunięte Treści Forum</h1>
</div>
<div class="section">
<h2>Usunięte Tematy ({{ deleted_topics|length }})</h2>
{% if deleted_topics %}
{% for topic in deleted_topics %}
<div class="deleted-item" id="topic-{{ topic.id }}">
<div class="deleted-header">
<div>
<strong>{{ topic.title }}</strong>
<div class="deleted-meta">
Autor: {{ topic.author.name or topic.author.email.split('@')[0] }}
&bull; Utworzono: {{ topic.created_at|local_time('%d.%m.%Y %H:%M') }}
</div>
</div>
<button class="btn-restore" onclick="restoreTopic({{ topic.id }})">
↩ Przywróć
</button>
</div>
<div class="deleted-content">
{{ topic.content[:300] }}{% if topic.content|length > 300 %}...{% endif %}
</div>
<div class="deleted-info">
Usunięto: {{ topic.deleted_at|local_time('%d.%m.%Y %H:%M') if topic.deleted_at else 'brak daty' }}
{% if topic.deleter %}przez {{ topic.deleter.name or topic.deleter.email.split('@')[0] }}{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<div class="empty-state">
Brak usuniętych tematów.
</div>
{% endif %}
</div>
<div class="section">
<h2>Usunięte Odpowiedzi ({{ deleted_replies|length }})</h2>
{% if deleted_replies %}
{% for reply in deleted_replies %}
<div class="deleted-item" id="reply-{{ reply.id }}">
<div class="deleted-header">
<div>
<div class="deleted-meta">
W temacie: <a href="{{ url_for('forum_topic', topic_id=reply.topic_id) }}" target="_blank">{{ reply.topic.title }}</a>
<br>Autor: {{ reply.author.name or reply.author.email.split('@')[0] }}
&bull; Utworzono: {{ reply.created_at|local_time('%d.%m.%Y %H:%M') }}
</div>
</div>
<button class="btn-restore" onclick="restoreReply({{ reply.id }})">
↩ Przywróć
</button>
</div>
<div class="deleted-content">
{{ reply.content[:300] }}{% if reply.content|length > 300 %}...{% endif %}
</div>
<div class="deleted-info">
Usunięto: {{ reply.deleted_at|local_time('%d.%m.%Y %H:%M') if reply.deleted_at else 'brak daty' }}
{% if reply.deleter %}przez {{ reply.deleter.name or reply.deleter.email.split('@')[0] }}{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<div class="empty-state">
Brak usuniętych odpowiedzi.
</div>
{% endif %}
</div>
{% endblock %}
{% block extra_js %}
function restoreTopic(topicId) {
if (!confirm('Przywrócić ten temat?')) return;
fetch(`/admin/forum/topic/${topicId}/restore`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('topic-' + topicId).remove();
} else {
alert(data.error || 'Błąd');
}
})
.catch(err => {
alert('Błąd połączenia');
});
}
function restoreReply(replyId) {
if (!confirm('Przywrócić tę odpowiedź?')) return;
fetch(`/admin/forum/reply/${replyId}/restore`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('reply-' + replyId).remove();
} else {
alert(data.error || 'Błąd');
}
})
.catch(err => {
alert('Błąd połączenia');
});
}
{% endblock %}