Current section

Files

Jump to

README.md

# PhoenixKitCustomerSupport
[![Elixir](https://img.shields.io/badge/Elixir-~%3E_1.18-4B275F)](https://elixir-lang.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
Customer support ticketing module for [PhoenixKit](https://github.com/BeamLabEU/phoenix_kit).
Provides a full ticketing system: create tickets, track status, add comments and attachments, manage agents. Extracted from PhoenixKit core (>= 1.7.104).
## Features
- **Ticket lifecycle**`open → in_progress → resolved → closed` with full status-history audit trail
- **Comments** — public comments visible to ticket owners, plus agent-only internal notes
- **Attachments** — file uploads on tickets and comments via `PhoenixKit.Modules.Storage`
- **Assignment** — assign tickets to support staff; assignment changes are recorded
- **Reopen flow** — closed tickets can be reopened by users or agents (configurable)
- **Admin and user LiveViews** — admin pages under `/admin/customer-support`, user-facing pages under `/dashboard/customer-support/tickets`
- **PubSub events** — per-user, per-ticket, and global topics for real-time updates
- **Auto-discovery** — implements `PhoenixKit.Module`; PhoenixKit finds it at startup with zero config
## Installation
Add to the host app's `mix.exs`:
```elixir
{:phoenix_kit_customer_support, "~> 0.3"}
```
Then `mix deps.get`. The module appears in the admin Modules page and sidebar automatically via `PhoenixKit.Module` auto-discovery.
Requires PhoenixKit core `~> 2.4`. `Ticket.changeset/2` calls `PhoenixKit.Utils.Slug.put_slug/3`, which core added in 2.4.0 (along with V168, which makes ticket slugs unique). Core 2.0.0 squashed the migration chain to a `V135` floor and refuses to migrate a database below it — check `mix phoenix_kit.status` before upgrading, and see core’s 2.0.0 / 2.4.0 CHANGELOGs.
This module owns and versions the future shape of its 4 tables (`phoenix_kit_tickets`, `phoenix_kit_ticket_comments`, `phoenix_kit_ticket_attachments`, `phoenix_kit_ticket_status_history`) through its own migration chain, `PhoenixKitCustomerSupport.Migrations`. Core's `V135`/`V168` still CREATE these 4 tables on every install — this chain's `V1` adopts that shape and stamps a version marker. It makes exactly one real change: `phoenix_kit_ticket_status_history.changed_by_uuid` is made NULLABLE (`ALTER COLUMN … DROP NOT NULL`), because core's baseline declares it `NOT NULL` while its own FK is `ON DELETE SET NULL` — a contradiction core's V164 documents but never resolves. Hosts installed from the squashed `V135` baseline (core ≥ 2.0.0) carry the `NOT NULL` and are relaxed by `V1`; older hosts that reached the current chain historically already have it nullable, so `V1` is a no-op there. `V1` also replaces any legacy descriptive `COMMENT` on `phoenix_kit_tickets` with the version marker. The `~> 2.4` floor above exists because `V1` must already include V168 (the unique slug index) for the adopted shape to match.
## Module integration
The package registers itself with PhoenixKit's module system. No manual router wiring needed — admin routes are auto-discovered at compile time via `route_module/0`.
## Routes
### Admin routes (registered by this package via `route_module/0`)
| Path | LiveView |
|------|----------|
| `/admin/customer-support` | `PhoenixKitCustomerSupport.Web.List` |
| `/admin/customer-support/tickets` | `PhoenixKitCustomerSupport.Web.List` |
| `/admin/customer-support/tickets/new` | `PhoenixKitCustomerSupport.Web.New` |
| `/admin/customer-support/tickets/:uuid` | `PhoenixKitCustomerSupport.Web.Details` |
| `/admin/customer-support/tickets/:uuid/edit` | `PhoenixKitCustomerSupport.Web.Edit` |
| `/admin/settings/customer-support` | `PhoenixKitCustomerSupport.Web.Settings` |
### User dashboard routes (wired by PhoenixKit core via `Code.ensure_loaded?` guards)
| Path | LiveView |
|------|----------|
| `/dashboard/customer-support/tickets` | `PhoenixKitCustomerSupport.Web.UserList` |
| `/dashboard/customer-support/tickets/new` | `PhoenixKitCustomerSupport.Web.UserNew` |
| `/dashboard/customer-support/tickets/:id` | `PhoenixKitCustomerSupport.Web.UserDetails` |
User-facing routes are registered by `PhoenixKitWeb.Integration` in the core library when this package is present — no additional router configuration is required in the host app.
## Settings
The following settings keys control this module's behaviour. They are managed via the admin Settings UI (`/admin/settings/customer-support`) or directly via `PhoenixKit.Settings`.
| Key | Default | Description |
|-----|---------|-------------|
| `customer_support_enabled` | `false` | Enables or disables the customer support module globally. |
| `customer_support_per_page` | `20` | Number of tickets shown per page in admin and user list views. |
| `customer_support_comments_enabled` | `true` | Allows users and agents to post comments on tickets. |
| `customer_support_internal_notes_enabled` | `true` | Enables internal (agent-only) notes on tickets. |
| `customer_support_attachments_enabled` | `true` | Allows file attachments to be added to tickets and comments. |
| `customer_support_allow_reopen` | `true` | Permits closed tickets to be reopened by users or agents. |
## Removing this module
There is deliberately **no automated uninstall**. `PhoenixKitCustomerSupport.Migrations.down/1`
never drops any of the 4 `phoenix_kit_ticket*` tables or a row in them, for
any target version — a host that merely removes this dependency from
`mix.exs` has not consented to deleting every customer's tickets, comments
(public and internal notes), attachments and status-change audit trail, and
a migration whose result depended on which packages happen to be compiled
in would be nondeterministic. Removing the data is therefore a deliberate,
manual operator step — remove `:phoenix_kit_customer_support` from `mix.exs`
first, then run, in FK-safe order (children before parents, substituting
your PhoenixKit schema prefix for `public`):
```sql
-- Only if you actually want every ticket and everything attached to it
-- gone for good.
DROP TABLE public.phoenix_kit_ticket_attachments;
DROP TABLE public.phoenix_kit_ticket_comments;
DROP TABLE public.phoenix_kit_ticket_status_history;
DROP TABLE public.phoenix_kit_tickets;
```
Dropping `phoenix_kit_tickets` last also removes the `pkcs_schema:<N>` version
marker, which is a `COMMENT` on that table — no separate step is needed.
While core's baseline still creates these tables (it does today), core's
`ExpectedSchema` manifest lists all 4 as required: `mix phoenix_kit.doctor`
then reports them missing, and `mix phoenix_kit.repair` recreates them —
**empty**. The rows are gone either way; only the empty tables come back.
To keep the rows (e.g. you plan to reinstall the module later), simply leave
the tables alone. The marker is inert once the module is gone, and on
reinstall it correctly reads as already adopted. Clearing it achieves
nothing: while the module is installed, the next `mix phoenix_kit.update`
re-stamps it.
## Development
```sh
mix deps.get
mix compile
mix test
```