{% extends "base.html" %} {% load common_extras %} {% comment %} One contact (issue #13). Four panes, each its own partial with its own refresh trigger, because they change independently: editing a field does not alter the channel list, and starting a flow does not alter the tags. A single container refreshed on every mutation would re-run every query on the page to redraw one line. Everything here is attacker-controlled — names, emails, platform usernames and profile picture URLs all arrive from strangers (SECURITY-BASELINE §2). Django autoescapes, nothing is marked safe, and the avatar URL is scheme-checked in apps/contacts/activity.py before it can become a src. {% endcomment %} {% block title %}{{ contact.display_name }} · Contacts · DemandTrail Messaging{% endblock %} {% block page_header %}
Added {{ contact.created_at }}{% if contact.last_interaction_at %} · last seen {{ contact.last_interaction_at }}{% endif %}
Each field saves on its own when you leave it.
{% else %}You have read-only access to this workspace.
{% endif %} {% for row in editable_fields %}Emptying a field removes its value entirely.
{% else %}No custom fields yet. {% if can_manage_crm %}Add one.{% endif %}
{% endif %}Removes {{ contact.display_name }} outright: their profile, custom field values, tags, channel identities, consent records, conversations and message bodies. Counters stay, anonymised. A suppressed email address is kept, because that is a fact about a mailbox rather than about this contact. This cannot be undone.