Implement more information displays

This commit is contained in:
2026-02-15 19:27:16 +00:00
parent c7e53909df
commit fb24e74ec4
13 changed files with 1421 additions and 271 deletions

View File

@@ -9,7 +9,6 @@
<div style="margin-bottom: 0.75rem; padding: 0.5rem 0.25rem; border-bottom: 1px solid rgba(0, 0, 0, 0.12);">
<p class="is-size-7 has-text-weight-semibold">Selected Person</p>
<h3 class="title is-5" style="margin-bottom: 0.25rem;">{{ person.name }}</h3>
<p class="is-size-7">Showing last {{ limit }} messages.</p>
<div class="tags" style="margin-top: 0.35rem;">
<a class="tag is-light" href="{% url 'ai_workspace_insight_detail' type='page' person_id=person.id metric='platform' %}">Platform {{ workspace_conversation.platform_type|title }}</a>
<a class="tag is-light" href="{% url 'ai_workspace_insight_detail' type='page' person_id=person.id metric='thread' %}">Thread {{ workspace_conversation.platform_thread_id|default:"-" }}</a>
@@ -126,72 +125,14 @@
</div>
<div id="ai-stage-{{ person.id }}" style="min-height: 7rem;">
<div id="ai-pane-{{ person.id }}-artifacts" class="ai-pane" style="display: none;">
<button
type="button"
class="button is-warning is-light is-small is-rounded"
onclick="giaWorkspaceRun('{{ person.id }}', 'artifacts', false); return false;">
<span class="icon is-small"><i class="fa-solid fa-table-columns"></i></span>
<span>Plan</span>
</button>
</div>
<div id="ai-pane-{{ person.id }}-summarise" class="ai-pane" style="display: none;">
<button
type="button"
class="button is-link is-light is-small is-rounded"
onclick="giaWorkspaceRun('{{ person.id }}', 'summarise', false); return false;">
<span class="icon is-small"><i class="fa-solid fa-list-check"></i></span>
<span>Summary</span>
</button>
</div>
<div id="ai-pane-{{ person.id }}-draft_reply" class="ai-pane">
<button
type="button"
class="button is-primary is-light is-small is-rounded"
onclick="giaWorkspaceRun('{{ person.id }}', 'draft_reply', false); return false;">
<span class="icon is-small"><i class="fa-solid fa-pen"></i></span>
<span>Draft</span>
</button>
</div>
<div id="ai-pane-{{ person.id }}-extract_patterns" class="ai-pane" style="display: none;">
<button
type="button"
class="button is-info is-light is-small is-rounded"
onclick="giaWorkspaceRun('{{ person.id }}', 'extract_patterns', false); return false;">
<span class="icon is-small"><i class="fa-solid fa-wave-square"></i></span>
<span>Patterns</span>
</button>
</div>
<div id="ai-pane-{{ person.id }}-artifacts" class="ai-pane" style="display: none;"></div>
<div id="ai-pane-{{ person.id }}-summarise" class="ai-pane" style="display: none;"></div>
<div id="ai-pane-{{ person.id }}-draft_reply" class="ai-pane"></div>
<div id="ai-pane-{{ person.id }}-extract_patterns" class="ai-pane" style="display: none;"></div>
</div>
</div>
</div>
<div id="ai-message-list-{{ person.id }}" style="max-height: 65vh; overflow-y: auto; padding-right: 0.25rem;">
{% if message_rows %}
{% for row in message_rows %}
<article class="media ai-message-row" data-ts="{{ row.message.ts }}" style="margin-bottom: 0.75rem;">
<div class="media-content">
<div
class="content"
style="margin-left: {% if row.direction == 'out' %}15%{% else %}0{% endif %}; margin-right: {% if row.direction == 'in' %}15%{% else %}0{% endif %};">
<div
style="margin-bottom: 0.25rem; padding: 0.6rem; border-radius: 6px; border: 1px solid rgba(0, 0, 0, 0.15); background: {% if row.direction == 'out' %}#f0f7ff{% else %}transparent{% endif %}; box-shadow: none;">
<p style="white-space: pre-wrap; margin-bottom: 0.35rem;">{{ row.message.text|default:"(no text)" }}</p>
<p class="is-size-7">
{{ row.ts_label }}
{% if row.message.custom_author %}
| {{ row.message.custom_author }}
{% endif %}
</p>
</div>
</div>
</div>
</article>
{% endfor %}
{% else %}
<p class="has-text-grey">No messages found for this contact.</p>
{% endif %}
</div>
</div>
<style>
@@ -266,88 +207,6 @@
}
}
function formatUtcLabel(tsMs) {
const ts = Number(tsMs || 0);
if (!ts) {
return "";
}
const dt = new Date(ts);
function pad(value) {
return String(value).padStart(2, "0");
}
return (
dt.getUTCFullYear()
+ "-" + pad(dt.getUTCMonth() + 1)
+ "-" + pad(dt.getUTCDate())
+ " " + pad(dt.getUTCHours())
+ ":" + pad(dt.getUTCMinutes())
+ " UTC"
);
}
function appendOutgoingMessage(tsMs, text, author) {
const host = document.getElementById("ai-message-list-" + personId);
if (!host) {
return;
}
const noMessages = host.querySelector("p.has-text-grey");
if (noMessages) {
noMessages.remove();
}
const article = document.createElement("article");
article.className = "media ai-message-row";
article.dataset.ts = String(Number(tsMs || Date.now()));
article.style.marginBottom = "0.75rem";
const mediaContent = document.createElement("div");
mediaContent.className = "media-content";
const contentWrap = document.createElement("div");
contentWrap.className = "content";
contentWrap.style.marginLeft = "15%";
contentWrap.style.marginRight = "0";
const bubble = document.createElement("div");
bubble.style.marginBottom = "0.25rem";
bubble.style.padding = "0.6rem";
bubble.style.borderRadius = "6px";
bubble.style.border = "1px solid rgba(0, 0, 0, 0.15)";
bubble.style.background = "#f0f7ff";
bubble.style.boxShadow = "none";
const bodyP = document.createElement("p");
bodyP.style.whiteSpace = "pre-wrap";
bodyP.style.marginBottom = "0.35rem";
bodyP.textContent = text || "(no text)";
const metaP = document.createElement("p");
metaP.className = "is-size-7";
metaP.textContent = formatUtcLabel(tsMs);
if (author) {
metaP.textContent += " | " + author;
}
bubble.appendChild(bodyP);
bubble.appendChild(metaP);
contentWrap.appendChild(bubble);
mediaContent.appendChild(contentWrap);
article.appendChild(mediaContent);
host.appendChild(article);
const maxRows = Math.max(5, Math.min(parseInt(widget.dataset.limit || "20", 10) || 20, 200));
const rows = host.querySelectorAll(".ai-message-row");
if (rows.length > maxRows) {
const removeCount = rows.length - maxRows;
for (let i = 0; i < removeCount; i += 1) {
if (rows[i] && rows[i].parentNode) {
rows[i].parentNode.removeChild(rows[i]);
}
}
}
host.scrollTop = host.scrollHeight;
}
function getCacheEntry(operation) {
const key = cacheKey(operation);
const raw = window.giaWorkspaceCache[key];
@@ -725,25 +584,6 @@
};
}
window.giaWorkspaceMessageListeners = window.giaWorkspaceMessageListeners || {};
const existingListener = window.giaWorkspaceMessageListeners[personId];
if (existingListener) {
document.body.removeEventListener("gia-message-sent", existingListener);
}
const messageSentListener = function(evt) {
const detail = (evt && evt.detail) ? evt.detail : {};
if (!detail || String(detail.person_id || "") !== personId) {
return;
}
appendOutgoingMessage(
Number(detail.ts || Date.now()),
String(detail.text || ""),
String(detail.author || "BOT")
);
};
document.body.addEventListener("gia-message-sent", messageSentListener);
window.giaWorkspaceMessageListeners[personId] = messageSentListener;
window.giaWorkspaceRun(personId, "artifacts", false);
})();
</script>