Fix issues with multiplatform conversation displays

This commit is contained in:
2026-02-16 11:42:53 +00:00
parent cf651a3bd4
commit a70faa3576
10 changed files with 489 additions and 78 deletions

View File

@@ -416,6 +416,11 @@
<a class="navbar-item" href="{% url 'ais' type='page' %}">
AI
</a>
{% if user.is_superuser %}
<a class="navbar-item" href="{% url 'system_settings' %}">
System
</a>
{% endif %}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,76 @@
{% extends "base.html" %}
{% block content %}
<section class="section">
<div class="container">
<h1 class="title is-4">System Maintenance</h1>
<p class="subtitle is-6">Superuser tools for data cleanup (current user scope).</p>
{% if notice_message %}
<article class="notification is-{{ notice_level|default:'info' }} is-light">
{{ notice_message }}
</article>
{% endif %}
<div class="columns is-multiline">
<div class="column is-12">
<article class="box">
<h2 class="title is-6">Purge Non-OSINT Data</h2>
<p class="is-size-7 has-text-grey" style="margin-bottom: 0.65rem;">
Removes message/workspace/AI/mitigation runtime rows but keeps OSINT setup objects.
</p>
<div class="tags" style="margin-bottom: 0.75rem;">
<span class="tag is-light">Chat Sessions: {{ counts.chat_sessions }}</span>
<span class="tag is-light">Messages: {{ counts.messages }}</span>
<span class="tag is-light">Queued: {{ counts.queued_messages }}</span>
<span class="tag is-light">Events: {{ counts.message_events }}</span>
<span class="tag is-light">Workspace: {{ counts.workspace_conversations }}</span>
<span class="tag is-light">Snapshots: {{ counts.workspace_snapshots }}</span>
<span class="tag is-light">AI Requests: {{ counts.ai_requests }}</span>
<span class="tag is-light">AI Results: {{ counts.ai_results }}</span>
<span class="tag is-light">Memory: {{ counts.memory_items }}</span>
<span class="tag is-light">Mitigation Plans: {{ counts.mitigation_plans }}</span>
</div>
<form method="post">
{% csrf_token %}
<input type="hidden" name="action" value="purge_non_osint">
<button type="submit" class="button is-danger is-light">Purge Non-OSINT</button>
</form>
</article>
</div>
<div class="column is-12">
<article class="box">
<h2 class="title is-6">Purge OSINT Setup Categories</h2>
<p class="is-size-7 has-text-grey" style="margin-bottom: 0.65rem;">
Category-specific cleanup controls.
</p>
<div class="buttons are-small" style="margin-bottom: 0.75rem;">
<form method="post" style="margin: 0;">
{% csrf_token %}
<input type="hidden" name="action" value="purge_osint_people">
<button type="submit" class="button is-warning is-light">Purge People ({{ counts.osint_people }})</button>
</form>
<form method="post" style="margin: 0;">
{% csrf_token %}
<input type="hidden" name="action" value="purge_osint_identifiers">
<button type="submit" class="button is-warning is-light">Purge Identifiers ({{ counts.osint_identifiers }})</button>
</form>
<form method="post" style="margin: 0;">
{% csrf_token %}
<input type="hidden" name="action" value="purge_osint_groups">
<button type="submit" class="button is-warning is-light">Purge Groups ({{ counts.osint_groups }})</button>
</form>
<form method="post" style="margin: 0;">
{% csrf_token %}
<input type="hidden" name="action" value="purge_osint_personas">
<button type="submit" class="button is-warning is-light">Purge Personas ({{ counts.osint_personas }})</button>
</form>
</div>
</article>
</div>
</div>
</div>
</section>
{% endblock %}

View File

@@ -12,6 +12,18 @@
data-service="{{ option.service }}"
data-identifier="{{ option.identifier }}"
data-person="{{ option.person_id }}"
data-signal-identifier="{{ option.signal_identifier|default:'' }}"
data-whatsapp-identifier="{{ option.whatsapp_identifier|default:'' }}"
data-instagram-identifier="{{ option.instagram_identifier|default:'' }}"
data-xmpp-identifier="{{ option.xmpp_identifier|default:'' }}"
data-signal-page-url="{{ option.signal_compose_url|default:'' }}"
data-whatsapp-page-url="{{ option.whatsapp_compose_url|default:'' }}"
data-instagram-page-url="{{ option.instagram_compose_url|default:'' }}"
data-xmpp-page-url="{{ option.xmpp_compose_url|default:'' }}"
data-signal-widget-url="{{ option.signal_compose_widget_url|default:'' }}"
data-whatsapp-widget-url="{{ option.whatsapp_compose_widget_url|default:'' }}"
data-instagram-widget-url="{{ option.instagram_compose_widget_url|default:'' }}"
data-xmpp-widget-url="{{ option.xmpp_compose_widget_url|default:'' }}"
data-page-url="{{ option.compose_url }}"
data-widget-url="{{ option.compose_widget_url }}"
{% if option.is_active %}selected{% endif %}>
@@ -2024,6 +2036,10 @@
if (!service || !identifier) {
return;
}
if (renderMode === "page" && pageUrl) {
window.location.assign(String(pageUrl));
return;
}
if (
String(thread.dataset.service || "").toLowerCase() === service
&& String(thread.dataset.identifier || "") === identifier
@@ -2065,13 +2081,6 @@
thread.dataset.lastTs = "0";
glanceState = { gap: null, metrics: [] };
renderGlanceItems([]);
if (renderMode === "page" && pageUrl) {
try {
window.history.replaceState({}, "", String(pageUrl));
} catch (err) {
// Ignore history API failures.
}
}
poll(true);
};
@@ -2685,14 +2694,33 @@
if (!selected) {
return;
}
const selectedService = selected.dataset.service || "";
const selectedIdentifier = selected.dataset.identifier || "";
const currentService = String(thread.dataset.service || "").toLowerCase();
const serviceIdentifierKey = currentService + "Identifier";
const servicePageUrlKey = currentService + "PageUrl";
const serviceWidgetUrlKey = currentService + "WidgetUrl";
let selectedService = currentService || (selected.dataset.service || "");
let selectedIdentifier = String(
selected.dataset[serviceIdentifierKey]
|| selected.dataset.identifier
|| ""
).trim();
const selectedPerson = selected.dataset.person || "";
const selectedPageUrl = (
let selectedPageUrl = (
renderMode === "page"
? selected.dataset.pageUrl
: selected.dataset.widgetUrl
? selected.dataset[servicePageUrlKey]
: selected.dataset[serviceWidgetUrlKey]
) || "";
if (!selectedIdentifier) {
selectedService = selected.dataset.service || selectedService;
selectedIdentifier = selected.dataset.identifier || "";
}
if (!selectedPageUrl) {
selectedPageUrl = (
renderMode === "page"
? selected.dataset.pageUrl
: selected.dataset.widgetUrl
) || "";
}
switchThreadContext(
selectedService,
selectedIdentifier,