# Panel Support Screen Hooks

https://dev.wisecp.com/es/admin-support-screen-hooks

The twenty-one placement points of the support screens: the ticket detail, the reply form, the list rows and the department forms.

## Overview

The placement points of the support screens live here: every part of the ticket detail, the list rows and the department forms.

A few points on the ticket detail hand you a **privilege flag**. It is not a gate: the core disables its own buttons with it, but it does not stop your output. If you show something that needs the privilege, do the check yourself.

## Reference

### A badge or button in the ticket title

uiadmin.tickets_detail.header_actions

`admin/tickets/detail` the title area

Appears in the title row of the ticket detail. It suits a case number in another system or a shortcut of your own.

Parameters 1

$ticketarrayThe active ticket record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_detail.header_actions', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the side column

uiadmin.ticket_detail.sidebar_top

`admin/tickets/detail` top of the side column

Appears in the side column of the ticket detail, above the first card.

Parameters 2

$ticketarrayThe active ticket record.

$opPrivboolWhether the viewer holds the operation privilege. ? This is **information**, not a gate: when false the core disables its own buttons but does not stop your output. If you show something that needs the privilege, **check it yourself**.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.sidebar_top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Adding an operation to the side column

uiadmin.ticket_detail.sidebar_actions

`admin/tickets/detail` an operation box

Appears among the operation boxes in the side column. It puts a ticket operation of your own beside the built-in ones.

Parameters 2

$ticketarrayThe active ticket record.

$opPrivboolWhether the viewer holds the operation privilege. ? This is **information**, not a gate: when false the core disables its own buttons but does not stop your output. If you show something that needs the privilege, **check it yourself**.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.sidebar_actions', 10, function ($ticket, $opPriv) {
    // Yetki bilgisi kapi DEGIL: kendiniz sinayin.
    if (!$opPriv) return null;

    return '<div class="operation-box"><button onclick="acmeEscalate('
         . (int) ($ticket['id'] ?? 0) . ')">Acme</button></div>';
});
```

### A row on the ticket details card

uiadmin.ticket_detail.details_card.meta

`admin/tickets/detail` the details card

Appears among the fields of the ticket details card. Add metadata of your own beside the core fields.

Parameters 1

$ticketarrayThe active ticket, with its mail source, department and reference in it.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.details_card.meta', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the conversation

uiadmin.ticket_detail.conversation.before

`admin/tickets/detail` above the conversation

Appears immediately above the reply thread. It suits context or a warning from another system.

Parameters 1

$ticketarrayThe active ticket record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.conversation.before', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the reply form

uiadmin.ticket_detail.reply_form.top

`admin/tickets/detail` top of the reply form

Appears above the box staff write their reply in. It suits a warning that should be seen before writing.

Parameters 2

$ticketarrayThe active ticket record.

$opPrivboolWhether the viewer holds the operation privilege. ? This is **information**, not a gate: when false the core disables its own buttons but does not stop your output. If you show something that needs the privilege, **check it yourself**.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.reply_form.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The reply form toolbar

uiadmin.ticket_detail.reply_form.toolbar

`admin/tickets/detail` the form toolbar

Appears in the toolbar of the reply form. Put your own insert or template button here.

Parameters 1

$ticketarrayThe active ticket record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.reply_form.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the reply editor

uiadmin.ticket_detail.reply_editor.after

`admin/tickets/detail` below the editor

Appears immediately below the text editor. It suits an extra option or a confirmation box before sending.

Parameters 1

$ticketarrayThe active ticket record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.reply_editor.after', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the canned replies

uiadmin.ticket_detail.canned_replies.after

`admin/tickets/detail` the language is separate

Appears below the canned reply options. The place to add a template source of your own.

Parameters 2

$ticketarrayThe active ticket record.

$client_langstringThe active interface language. Canned replies load in the customer’s language, and since the template does not hold that value the interface language is passed instead. The two **may differ**.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.canned_replies.after', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the internal note form

uiadmin.ticket_detail.note_form.bottom

`admin/tickets/detail` the internal note form

Appears below the internal note box. Notes are never shown to the customer.

Parameters 1

$ticketarrayThe active ticket record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.note_form.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A new tab on the ticket detail

uiadmin.ticket_detail.tabs

`admin/tickets/detail` an object, not an array

Runs once the tabs of the ticket detail are built. You do not return HTML: you add the tab through the object’s method.

Parameters 2

$tabobjectThe tab object. Being an object, it changes for good without a by-link mark.

$ticketarrayThe full ticket record.

Return 1

voidThe return is **not used**. This point shows no HTML.

Listener PHP

```php
Hook::add('ui:admin.ticket_detail.tabs', 10, function ($tab, $ticket) {
    $tab->add('acme', 'Acme', Acme::renderTab((int) ($ticket['id'] ?? 0)));
});
```

### The very bottom of the ticket page

uiadmin.tickets_detail.bottom

`admin/tickets/detail` end of the page

Appears at the very end of the page.

Parameters 1

$ticketarrayThe ticket record on screen.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_detail.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A badge on a list row

uiadmin.tickets_list.row_badges

`admin/tickets` per row

Appears on **every row** of the ticket list. It puts a status badge of your own beside the core ones.

Parameters 1

$modelarrayThe row data: id, status, read mark, department and title. ? The hook runs per row, so a listener querying the database here produces **hundreds of queries per page**. Collect what you need beforehand.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_list.row_badges', 10, function ($model) {
    // SATIR BASINA calisir: burada sorgu yapmayin, onceden toplayin.
    if (!Acme::isEscalated((int) ($model['id'] ?? 0))) return null;

    return '<span class="badge bg-danger">Acme</span>';
});
```

### The ticket list toolbar

uiadmin.tickets_list.toolbar

`admin/tickets` no parameters

Appears in the button group above the ticket list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the table on the ticket list

uiadmin.tickets_list.before_table

`admin/tickets` no parameters

Appears immediately above the ticket table.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The department list toolbar

uiadmin.department_list.toolbar

`admin/tickets/departments` no parameters

Appears in the toolbar of the department list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.department_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the table on the department list

uiadmin.department_list.before_table

`admin/tickets/departments` no parameters

Appears immediately above the department table.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.department_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the ticket creation form

uiadmin.tickets_edit.before_content

`admin/tickets` the customer may be empty

Appears above the form staff use to open a ticket for a customer.

Parameters 1

$userarrayThe customer pre-selected for the form. It **arrives empty** when no customer is chosen yet.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_edit.before_content', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the ticket creation form

uiadmin.tickets_edit.bottom

`admin/tickets` the customer may be empty

Appears below the same form, at the bottom of the page.

Parameters 1

$userarrayThe customer pre-selected for the form. It **arrives empty** when no customer is chosen yet.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.tickets_edit.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the department form

uiadmin.department_edit.before_content

`admin/tickets/departments` empty when creating

Appears above the department add and edit form.

Parameters 1

$detailarrayThe department being edited. It is **empty when creating**: test before reaching for an id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.department_edit.before_content', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the department form

uiadmin.department_edit.bottom

`admin/tickets/departments` empty when creating

Appears below the same form.

Parameters 1

$detailarrayThe department being edited. It is **empty when creating**: test before reaching for an id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.department_edit.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

## Pitfalls

> **The privilege flag is not a gate**
> 
> The privilege parameter on the ticket detail **tells you whether the viewer holds it**; it does not block your output on its own. If you would rather not show an operation button to somebody without the privilege, put the condition in **your own listener**. The real check stays in the operation on the server: hiding here is only visibility.

> **The row badge runs on every row**
> 
> The list badge point is called **separately for every ticket** on the page. A listener doing a database query or an outside call inside it produces fifty queries on a fifty-row page and slows the list noticeably. Collect what you need once and read it from memory.

## Related Articles

- Support Ticket Hooks
- [Ticket View Hooks](https://dev.wisecp.com/en/ticket-view-hooks)
- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
