User Support
Ticket system for communicating with users
Ticket Update Component
The supportTicketUpdate component lets the signed-in user edit their original ticket or one of their own replies, including its attachments.
| Property | Description |
|---|---|
| ticketPage | The page with the Ticket component to return to after saving. |
Basic Usage
The page URL must include an :id parameter. The mode query parameter sets what the ID refers to.
- With
?mode=ticket, the page edits the original ticket, and:idis the ticket ID. - Without it, or with any other value, the page edits a reply, and
:idis the message ID.
The Ticket component builds both links, as ticket.url with ?mode=ticket added and as message.url. The component only edits the records of the signed-in user, so restrict the page to signed-in users with the RainLab.User session component.
title = "Update Message"
url = "/support/update/:id"
layout = "default"
[session]
security = "user"
redirect = "account/login"
[supportTicketUpdate]
ticketPage = "support/ticket"
==
{% component "supportTicketUpdate" %}
The default form shows the subject in ticket mode, the message, a Minor update checkbox, the current attachments with a Delete button on each, and a field for new attachments.
Page Variables
The component object provides the following values.
| Variable | Description |
|---|---|
supportTicketUpdate.model |
The ticket in ticket mode, or the message in message mode. It is null when the signed-in user cannot edit the record. |
supportTicketUpdate.returnUrl |
The address of the ticket on the ticketPage page, pointing at the message in message mode. |
The record provides its content and attachments, and in ticket mode its subject. In message mode, model.ticket is the ticket that the message belongs to.
The component also sets these page variables.
| Variable | Description |
|---|---|
updateMode |
The edit mode, which is ticket or message. |
ticketPage |
The ticketPage property value. |
The following page edits the record with its own markup. It posts the mode field and keeps the attachment list in the partialUpdateAttachments element, which the delete buttons update.
title = "Update Message"
url = "/support/update/:id"
layout = "default"
[session]
security = "user"
redirect = "account/login"
[supportTicketUpdate]
ticketPage = "support/ticket"
==
{% set model = supportTicketUpdate.model %}
{% set ticket = model and updateMode == 'message' ? model.ticket : model %}
{% if not model %}
<p>
Message cannot be found.
</p>
{% elseif ticket.closed_at %}
<p>
This ticket has been closed.
</p>
{% else %}
{{ form_ajax('onUpdateMessage', { files: true, flash: true, validate: true }) }}
<input type="hidden" name="mode" value="{{ updateMode }}" />
{% if updateMode == 'ticket' %}
<input name="subject" type="text" maxlength="255" value="{{ model.subject }}" />
<div data-validate-for="subject"></div>
{% endif %}
<textarea name="content" rows="8">{{ model.content }}</textarea>
<div data-validate-for="content"></div>
<input type="hidden" name="minor_update" value="0" />
<label>
<input name="minor_update" type="checkbox" value="1" checked />
Minor update
</label>
<div id="partialUpdateAttachments">
{% partial 'supportTicketUpdate::update-attachments' attachments=model.attachments %}
</div>
<input name="files[]" type="file" multiple />
<div data-validate-for="files"></div>
<button type="submit" data-attach-loading>
Save
</button>
<a href="{{ supportTicketUpdate.returnUrl }}">
Cancel
</a>
{{ form_close() }}
{% endif %}
AJAX Handlers
The component provides the following AJAX handlers.
| Handler | Description |
|---|---|
| onUpdateMessage | Validates and saves the edited record with its attachments, then returns to the ticket page. |
| onDeleteAttachment | Marks an attachment for removal when the form is saved, and refreshes the attachment list. |
Saving Changes
The onUpdateMessage handler accepts the following fields.
| Field | Description |
|---|---|
mode |
The edit mode. Post it with the form, as the default form does, so the handler edits the same record as the page. |
subject |
The subject, in ticket mode only. Required, and at most 255 characters. |
content |
The text, in Markdown. Required, and at most 50,000 characters. |
minor_update |
When posted as 0, staff receive the ticket-message-updated mail. When it is 1 or missing, the edit counts as minor and sends no mail. |
files[] |
Files to attach. See Attachments. |
redirect |
Optional. A page name, or a path on this site, that replaces the ticketPage property. |
The form's session key, which form_ajax() adds as _session_key, links the new attachments and the removals to the save. After saving, the handler sets the flash message The message has been updated successfully. and redirects to the returnUrl address.
To let the user choose whether staff are notified, post a hidden 0 value before the checkbox, as the default form does, so that unticking the box sends 0.
<input type="hidden" name="minor_update" value="0" />
<label>
<input name="minor_update" type="checkbox" value="1" checked />
Minor update
</label>
See Staff Recipients for who receives the mail.
Deleting Attachments
The onDeleteAttachment handler accepts the following fields.
| Field | Description |
|---|---|
file_id |
The ID of the attachment to remove. |
_session_key |
The session key of the edit form. Required. |
The handler marks the file for removal with the session key, and the file is removed when the form is saved. Leaving the page without saving keeps the file. The handler then sets the attachments page variable to the remaining attachments, and showDelete to true, for the update-attachments partial.
Place the button inside the edit form, so that the request sends the form's session key and mode.
{% for attachment in attachments %}
<a href="{{ attachment.path }}">
{{ attachment.file_name }}
</a>
<button
type="button"
data-request="onDeleteAttachment"
data-request-data="{ file_id: {{ attachment.id }} }"
data-request-update="{ '@update-attachments': '#partialUpdateAttachments' }"
data-request-flash>
Delete
</button>
{% endfor %}
Partials
The component renders the following partials.
| Partial | Description |
|---|---|
| default | Wraps the edit form in the responsiv-support element, or shows a notice when the record cannot be found or its ticket is closed. |
| update-attachments | The current attachments, each with a Delete button. |
| flash-messages | Shared. Shows the flash messages. |
To change one of them, copy it into the partials/supportTicketUpdate folder of your theme. See Overriding Partials.
Rules
- Signed-in users. The
onUpdateMessagehandler refuses a guest with You should be logged in. - Ownership. In ticket mode, the ticket must belong to the signed-in user. In message mode, the message must be one of the user's own replies on their ticket, so staff replies and internal messages cannot be edited. Otherwise
modelis null and both handlers refuse with Message cannot be found. - Closed tickets. Both handlers refuse to change a closed ticket, or a reply on one, with This ticket has been closed.
- Ticket type. Only the subject and content are saved. A posted ticket type is ignored.
- Validation. Errors are reported under the
subjectandcontentfields. - Attachments. New files follow the attachment rules, where
attachmentMaxFilescounts the files added in one save, and errors are reported under thefilesfield. TheonDeleteAttachmenthandler only removes files of the record being edited.
Previous: Ticket Submit