{% comment %} The contact panel (HANDOFF §3, Inbox): who this is, the thread's labels and the person's tags, and the automation that last ran for them. Attacker-controlled here too (SECURITY-BASELINE §2): the contact's name, email and phone came from a platform profile, and `platform_user_id` is a raw chat id or PSID. All of it renders escaped; none of it becomes a URL. Pausing lives in the thread's status bar, not here — one control for one thing. The panel only says so while a pause is on, with the way back out. {% endcomment %} {% load common_extras %}
{% comment %} Only shown where the panel opens over the thread (below `lg`), because there it covers the header button that opened it. {% endcomment %}

Contact

Name
{{ contact.display_name }}
{% for row in identities %}
{{ row.get_platform_display }}
{{ row.platform_user_id }}
{% endfor %} {% if contact.email %}
Email
{{ contact.email }}
{% endif %} {% if contact.phone %}
Phone
{{ contact.phone }}
{% endif %}
First seen
{{ contact.created_at|date:"j M Y" }}
Opt-in
{% comment %} The address this conversation is on, because it is the one a reply here goes to. A word and a colour, never the colour alone. {% endcomment %} {% if identity.opted_out_at %}
Opted out {{ identity.opted_out_at|date:"j M" }}
{% elif identity.opt_in %}
Subscribed
{% else %}
Not recorded
{% endif %}
Open contact
{% if thread_labels or can_reply and thread_label_options %}

Labels

{% comment %} `chip.color` is the vetted value from apps.inbox.rendering; the stored column never reaches a style attribute. See LabelChip. {% endcomment %} {% for chip in thread_labels %} {{ chip.name }} {% if can_reply %}
{% csrf_token %}
{% endif %}
{% endfor %} {% if can_reply and thread_label_options %}
{% csrf_token %} {% for option in thread_label_options %} {% endfor %}
{% endif %}
{% endif %}

Tags

{% for tag in contact_tags %} {{ tag.name }} {% if can_edit_contact %}
{% csrf_token %}
{% endif %}
{% empty %} {% if not can_edit_contact or not available_tags %}None yet.{% endif %} {% endfor %} {% if can_edit_contact and available_tags %} {% comment %} Only tags this workspace already has. Creating one is `manage_crm` and lives on the contacts settings page — the split SPEC §4.2 draws between the tag vocabulary and one contact's values, which is what lets an agent use this control at all. {% endcomment %}
{% csrf_token %} {% for tag in available_tags %} {% endfor %}
{% endif %}

Automation

{% if is_paused %}
Paused until {{ conversation.automation_paused_until|time:"H:i" }} Flows will not reply to this contact until then. {% if can_reply %}
{% csrf_token %}
{% endif %}
{% endif %} {% if last_run %}
{{ last_run.execution.flow.name }} {% if last_run.is_live %}{{ last_run.execution.get_status_display }} · started {{ last_run.execution.created_at|timesince }} ago{% else %}Last ran {{ last_run.execution.updated_at|timesince }} ago{% endif %} · {{ last_run.sent }} message{{ last_run.sent|pluralize }} sent {% if last_run.is_live and can_reply %}
{% csrf_token %}
{% endif %}
{% elif not is_paused %}

Nothing has run for this contact yet.

{% endif %}
{% if custom_fields %}

Fields

{% for field in custom_fields %}
{{ field.name }}
{{ field.value }}
{% endfor %}
{% endif %}