Files
simplex-manager/manager/templates/notifications.html
Jon c1bb9cb955 Add chat actions, channels/groups mgmt, directory + deadmans bots, network status
Profiles/bots (profiles.py, main.py):
- Surface real send errors; fix group send and member-count staleness (refresh on view)
- Group/channel actions: join, leave, owner delete; consistent member counts
- Contacts: always-visible Chat, plus Clear chat and Delete contact
- Support bot: OpenAI-compatible LLM backend (Grok/Ollama/OpenAI) per-bot config
- Deadmans bot: check-in window, trigger message, recipients, owner
- Directory bot: add-to-group registration, super-user /approve /reject /list, search,
  publishes listing.json in the website schema (directory.py registry module)
- Profile edit (name/bio/avatar) + avatars on list pages
- Global status + /network page (operators, SMP/XFTP servers) and Settings network info

UI (templates):
- Chat rooms; collapsible left sidebar with notifications + network widget
- Per-directory-bot website generated on creation (name substituted)
- Matrix theme; copy/hyperlink addresses; site footer

Ignore runtime bot state and generated directory sites.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:26:16 +01:00

64 lines
2.3 KiB
HTML

{% extends "base.html" %}
{% block title %}Notifications — SimpleX Manager{% endblock %}
{% block head %}
<style>
.notif-item { display: block; padding: 14px 18px; border-bottom: 1px solid var(--border);
text-decoration: none; color: var(--text); border-left: 3px solid transparent; }
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--bg); }
.notif-item.unread { border-left-color: var(--accent); }
.notif-text { margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 540px; }
</style>
{% endblock %}
{% block content %}
<div class="flex-between" style="margin-bottom: 24px;">
<h1 style="margin:0;">Notifications</h1>
{% if items %}
<button class="btn btn-ghost" onclick="markAllRead()">Mark all read</button>
{% endif %}
</div>
{% if items %}
<div class="card" style="padding:0;">
{% for n in items %}
<a class="notif-item {% if not n.read %}unread{% endif %}"
href="/profile/{{ n.profile_id }}/chat/{{ n.chat_type }}/{{ n.chat_id }}">
<div class="flex-between">
<div style="min-width:0;">
<div><strong>{{ n.sender or 'Someone' }}</strong> <span class="muted">→ {{ n.profile_name }}</span></div>
<div class="muted notif-text">{{ n.text }}</div>
</div>
<span class="muted notif-time" data-ts="{{ n.ts }}" style="flex-shrink:0;margin-left:12px;"></span>
</div>
</a>
{% endfor %}
</div>
{% else %}
<div class="card" style="text-align:center;padding:48px;color:var(--muted);">
No notifications yet. Incoming messages across all accounts will appear here.
</div>
{% endif %}
<script>
function _ntoken(){ return document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || ''; }
async function markAllRead() {
await fetch('/api/notifications/read', { method: 'POST', headers: { 'X-Token': _ntoken() } });
location.reload();
}
// Localize timestamps
document.querySelectorAll('.notif-time').forEach(el => {
const d = new Date(el.dataset.ts);
if (!isNaN(d)) el.textContent = d.toLocaleString([], {month:'short', day:'numeric', hour:'2-digit', minute:'2-digit'});
});
// Mark read shortly after viewing so the badge clears (keeps this view's highlights)
setTimeout(() => {
fetch('/api/notifications/read', { method: 'POST', headers: { 'X-Token': _ntoken() } });
}, 1200);
</script>
{% endblock %}