82 lines
3.1 KiB
HTML
82 lines
3.1 KiB
HTML
{% extends shell_base %}
|
|
|
|
{% block title %}{{ label }} · CheckPoint Ehrenamt{% endblock %}
|
|
|
|
{% block content %}
|
|
<p><a class="cp-muted" href="{{ url_for('main.team') }}">← Team</a></p>
|
|
<h1>{{ label }}</h1>
|
|
{% if kanal.nur_admin_darf_posten %}
|
|
<p class="cp-muted">Nur das Team-Management postet hier. Alle lesen mit.</p>
|
|
{% endif %}
|
|
|
|
{# data-* steuern das Polling (siehe Skript unten). neu-base + id = JSON-Endpunkt. #}
|
|
<ul class="cp-chat" id="cp-chat-liste"
|
|
data-neu-base="{{ url_for('chat.kanal', art=kanal.art) }}/seit/"
|
|
data-letzte="{{ letzte_id }}"
|
|
data-meine="{{ current_user.id }}">
|
|
{% for n in nachrichten %}
|
|
<li class="cp-msg{{ ' cp-msg--eigen' if n.autor_id == current_user.id else '' }}">
|
|
<div class="cp-msg__meta">{{ n.autor.anzeigename }} · {{ zeit(n.erstellt_am) }}</div>
|
|
<div class="cp-msg__text">{{ n.text }}</div>
|
|
</li>
|
|
{% else %}
|
|
<li class="cp-muted" id="cp-chat-leer">Noch keine Nachrichten.</li>
|
|
{% endfor %}
|
|
</ul>
|
|
|
|
{% if darf_posten %}
|
|
<form method="post" action="{{ url_for('chat.posten', art=kanal.art) }}" class="cp-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<div class="cp-field">
|
|
<label for="text">Nachricht</label>
|
|
<textarea id="text" name="text" rows="3" maxlength="2000" required
|
|
placeholder="Schreib etwas …"></textarea>
|
|
</div>
|
|
<button type="submit" class="cp-btn cp-btn--primary">Senden</button>
|
|
</form>
|
|
{% endif %}
|
|
|
|
{# Einzige v1-JS-Ausnahme: kleines fetch-Polling für neue Nachrichten.
|
|
Einfügen ausschließlich per textContent → kein XSS über Nachrichtentext. #}
|
|
<script>
|
|
(function () {
|
|
const liste = document.getElementById("cp-chat-liste");
|
|
if (!liste) return;
|
|
const basis = liste.dataset.neuBase;
|
|
const meine = Number(liste.dataset.meine || 0);
|
|
let letzte = Number(liste.dataset.letzte || 0);
|
|
|
|
function anhaengen(n) {
|
|
const leer = document.getElementById("cp-chat-leer");
|
|
if (leer) leer.remove();
|
|
const li = document.createElement("li");
|
|
li.className = "cp-msg" + (n.autor_id === meine || n.eigene ? " cp-msg--eigen" : "");
|
|
const meta = document.createElement("div");
|
|
meta.className = "cp-msg__meta";
|
|
meta.textContent = n.autor + " · " + n.zeit;
|
|
const txt = document.createElement("div");
|
|
txt.className = "cp-msg__text";
|
|
txt.textContent = n.text;
|
|
li.appendChild(meta);
|
|
li.appendChild(txt);
|
|
liste.appendChild(li);
|
|
}
|
|
|
|
async function holen() {
|
|
try {
|
|
const r = await fetch(basis + letzte, { headers: { "X-Requested-With": "fetch" } });
|
|
if (!r.ok) return;
|
|
const daten = await r.json();
|
|
if (!daten.nachrichten.length) return;
|
|
for (const n of daten.nachrichten) {
|
|
anhaengen(n);
|
|
if (n.id > letzte) letzte = n.id;
|
|
}
|
|
window.scrollTo(0, document.body.scrollHeight);
|
|
} catch (e) { /* stiller Wiederholversuch beim nächsten Intervall */ }
|
|
}
|
|
|
|
setInterval(holen, 5000);
|
|
})();
|
|
</script>
|
|
{% endblock %}
|