{% comment %} The compose box. Outside the polled region on purpose — see inbox/_thread.html. One form serves a reply and an internal note. They differ only in where they post: apps.messaging.services.send_as_agent(internal=True) stores a note as a message and never calls an adapter, which is SPEC §14's definition of one, and keeping that decision in the URL rather than in a request flag means the note path is a different endpoint with its own test rather than a boolean somebody could flip by hand. "Send later" and "Reminder" open as popovers above the box (`sheet`), not as panels that unfold under it: the box stays the size of a message, and the thread above keeps its height. {% endcomment %} {% load common_extras %} {% if can_reply %}
{% csrf_token %} {% comment %} The idempotency key for this composition (SPEC §9.4). Rendered once with the box, so a double-click, a refresh-resubmit or an over-eager retry all arrive carrying the key the first attempt used and collapse on message_unique_conv_idem instead of sending twice. A successful send refetches this partial, which mints a new one. {% endcomment %} {% comment %} Reply and Internal note as two pills over one box (HANDOFF §3, Inbox). They share every field and differ only in the endpoint; choosing before typing, and the box changing colour for a note, means nobody writes a note believing it will be sent — or the other way round. {% endcomment %}
Sending pauses automation for {{ pause_minutes }} minutes. Only your team sees notes.
{% comment %} No `required`: with the attachment button beside it a picture on its own is a legitimate reply, and a browser-side `required` would refuse to submit one. The server is the authority — _outbound_body raises _ComposeError for a message with no blocks at all, and the toast says so. {% endcomment %} {% comment %} Attachments picked from the library (#16). Ids only — the picker's contract says "Store `id`. Never store `url` — it is minted per request" — so the chips carry ids and the view resolves each to a signed delivery URL at send time, scoped to this workspace. {% endcomment %}
{% comment %} The button is offered only where the platform can carry media, read from apps.channels.capabilities in the view. No platform branching in this file, ever. {% endcomment %} {% if media_kinds %} {% endif %} {% comment %} Send is the one orange control in the inbox (HANDOFF §3). In the note tab it gives way to "Add note", which posts the same fields to the note endpoint — hx-post on the button overrides the form's. Same token: whichever is pressed, pressing it twice is still one message. {% endcomment %}
{% comment %} The library picker. A list the agent chooses from, not a bulk add. Search re-queries the server rather than filtering the page in the browser, because the payload is one keyset page — an asset past it is unreachable by filtering what already arrived. {% endcomment %} {% comment %} Compose now, send later (SPEC §14). Inside the reply's form: the same fields, a different endpoint — the shape "Add note" uses — so the scheduled body is built by exactly the code that builds a live one. {% endcomment %}
{% comment %} Reminders. Their own form, not a third button on the composer's: a reminder carries no message body, and hx-include="closest form" would post the half-written reply with it. It still opens from the composer's "Reminder" button, through the `sheet` both forms share. {% endcomment %}
{% else %}
You can read this inbox but not reply to it.
{% endif %}