@escalated-dev/escalated 0.8.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +388 -361
  3. package/package.json +85 -84
  4. package/src/components/ActiveChatsPanel.vue +246 -246
  5. package/src/components/AdminDashboard.stories.js +1423 -1423
  6. package/src/components/AttachmentList.vue +65 -65
  7. package/src/components/ChatActionBar.vue +226 -226
  8. package/src/components/ChatBubble.vue +162 -162
  9. package/src/components/ChatComposer.vue +308 -308
  10. package/src/components/ChatQueue.vue +222 -222
  11. package/src/components/ChatThread.vue +197 -197
  12. package/src/components/CustomTicketActions.stories.js +71 -0
  13. package/src/components/CustomTicketActions.vue +101 -0
  14. package/src/components/EscalatedLayout.vue +628 -604
  15. package/src/components/FollowButton.vue +20 -1
  16. package/src/components/MentionDropdown.vue +154 -154
  17. package/src/components/MetricComparison.vue +89 -89
  18. package/src/components/PercentileChart.vue +67 -67
  19. package/src/components/PeriodSelector.vue +98 -98
  20. package/src/components/PresenceIndicator.vue +228 -213
  21. package/src/components/ReplyComposer.vue +336 -336
  22. package/src/components/ReplyThread.vue +153 -153
  23. package/src/components/ReportChart.vue +395 -395
  24. package/src/components/ReportExportButton.vue +108 -108
  25. package/src/components/SaveViewDialog.vue +172 -172
  26. package/src/components/SavedViewSidebar.vue +208 -208
  27. package/src/components/SkillTagManager.vue +3 -0
  28. package/src/components/SnoozeButton.vue +247 -247
  29. package/src/components/TicketFilters.vue +270 -270
  30. package/src/components/TicketList.vue +655 -655
  31. package/src/components/TicketSidebar.vue +4 -0
  32. package/src/components/TicketSplitDialog.vue +98 -98
  33. package/src/components/TicketSubjects.stories.js +63 -0
  34. package/src/components/TicketSubjects.vue +107 -0
  35. package/src/components/TwoFactorSetup.vue +1 -37
  36. package/src/components/VariableTokenInput.vue +111 -111
  37. package/src/components/WorkflowActionConfig.vue +287 -287
  38. package/src/components/WorkflowActionList.vue +350 -350
  39. package/src/components/WorkflowConditionBuilder.vue +265 -265
  40. package/src/components/WorkflowTriggerSelector.vue +125 -125
  41. package/src/components/admin/newsletters/AnalyticsTiles.stories.js +14 -0
  42. package/src/components/admin/newsletters/AnalyticsTiles.vue +55 -0
  43. package/src/components/admin/newsletters/DeliveriesTable.stories.js +28 -0
  44. package/src/components/admin/newsletters/DeliveriesTable.vue +104 -0
  45. package/src/components/admin/newsletters/DynamicFilterBuilder.stories.js +11 -0
  46. package/src/components/admin/newsletters/DynamicFilterBuilder.vue +53 -0
  47. package/src/components/admin/newsletters/ListMemberTable.stories.js +12 -0
  48. package/src/components/admin/newsletters/ListMemberTable.vue +53 -0
  49. package/src/components/admin/newsletters/MarkdownEditor.stories.js +6 -0
  50. package/src/components/admin/newsletters/MarkdownEditor.vue +53 -0
  51. package/src/components/admin/newsletters/MergeFieldDropdown.stories.js +6 -0
  52. package/src/components/admin/newsletters/MergeFieldDropdown.vue +84 -0
  53. package/src/components/admin/newsletters/PreviewIframe.stories.js +7 -0
  54. package/src/components/admin/newsletters/PreviewIframe.vue +40 -0
  55. package/src/components/admin/newsletters/SummaryTiles.stories.js +8 -0
  56. package/src/components/admin/newsletters/SummaryTiles.vue +63 -0
  57. package/src/composables/useChat.js +187 -187
  58. package/src/composables/useI18n.js +102 -102
  59. package/src/composables/useMentions.js +134 -134
  60. package/src/composables/usePermissions.js +31 -0
  61. package/src/composables/useRealtime.js +182 -182
  62. package/src/index.js +85 -84
  63. package/src/locales/README.md +13 -13
  64. package/src/locales/ar.json +727 -727
  65. package/src/locales/de.json +690 -690
  66. package/src/locales/en.json +889 -729
  67. package/src/locales/es.json +691 -691
  68. package/src/locales/fr.json +691 -691
  69. package/src/locales/index.js +16 -16
  70. package/src/locales/it.json +727 -727
  71. package/src/locales/ja.json +727 -727
  72. package/src/locales/ko.json +727 -727
  73. package/src/locales/nl.json +727 -727
  74. package/src/locales/pl.json +727 -727
  75. package/src/locales/pt-BR.json +727 -727
  76. package/src/locales/ru.json +727 -727
  77. package/src/locales/tr.json +727 -727
  78. package/src/locales/zh-CN.json +727 -727
  79. package/src/pages/Admin/Automations/Form.vue +280 -0
  80. package/src/pages/Admin/Automations/Index.vue +230 -0
  81. package/src/pages/Admin/Newsletters/Compose.vue +192 -0
  82. package/src/pages/Admin/Newsletters/Edit.vue +24 -0
  83. package/src/pages/Admin/Newsletters/Index.vue +141 -0
  84. package/src/pages/Admin/Newsletters/Lists/Create.vue +64 -0
  85. package/src/pages/Admin/Newsletters/Lists/Index.vue +59 -0
  86. package/src/pages/Admin/Newsletters/Lists/Show.vue +53 -0
  87. package/src/pages/Admin/Newsletters/Settings.vue +85 -0
  88. package/src/pages/Admin/Newsletters/Show.vue +140 -0
  89. package/src/pages/Admin/Newsletters/Templates/Create.vue +11 -0
  90. package/src/pages/Admin/Newsletters/Templates/Index.vue +54 -0
  91. package/src/pages/Admin/Newsletters/Templates/Show.vue +65 -0
  92. package/src/pages/Admin/Newsletters/usePreview.js +44 -0
  93. package/src/pages/Admin/Plugins/Index.vue +10 -2
  94. package/src/pages/Admin/Reports/AgentDetail.vue +132 -132
  95. package/src/pages/Admin/Reports/AgentRanking.vue +246 -246
  96. package/src/pages/Admin/Reports/Cohorts.vue +180 -180
  97. package/src/pages/Admin/Reports/Comparison.vue +141 -141
  98. package/src/pages/Admin/Reports/Dashboard.vue +226 -226
  99. package/src/pages/Admin/Reports/ResolutionTimes.vue +164 -164
  100. package/src/pages/Admin/Reports/ResponseTimes.vue +164 -164
  101. package/src/pages/Admin/Reports/SlaTrends.vue +183 -183
  102. package/src/pages/Admin/Settings/DatabaseConnection.vue +228 -0
  103. package/src/pages/Admin/Settings/PublicTickets.vue +163 -0
  104. package/src/pages/Admin/Settings/SsoSettings.vue +157 -4
  105. package/src/pages/Admin/Settings/TwoFactor.vue +32 -6
  106. package/src/pages/Admin/Settings.vue +1008 -1008
  107. package/src/pages/Admin/Skills/Form.vue +30 -10
  108. package/src/pages/Admin/Tickets/Index.vue +126 -126
  109. package/src/pages/Admin/Tickets/Show.vue +254 -249
  110. package/src/pages/Admin/Users/Index.vue +145 -145
  111. package/src/pages/Admin/Webhooks/DeliveryLog.vue +1 -2
  112. package/src/pages/Admin/Workflows/Builder.vue +207 -207
  113. package/src/pages/Admin/Workflows/Form.vue +24 -0
  114. package/src/pages/Admin/Workflows/Index.vue +235 -235
  115. package/src/pages/Admin/Workflows/Logs.vue +286 -286
  116. package/src/pages/Agent/TicketIndex.vue +112 -112
  117. package/src/pages/Agent/TicketShow.vue +547 -494
  118. package/src/pages/Customer/Index.vue +56 -56
  119. package/src/pages/Customer/KnowledgeBase/Article.vue +129 -129
  120. package/src/pages/Plugin/Page.vue +61 -0
  121. package/src/plugin.js +175 -175
  122. package/src/utils/mentionHighlight.js +24 -24
  123. package/src/widget/EscalatedWidget.vue +804 -804
  124. package/src/widget/index.js +254 -254
package/README.md CHANGED
@@ -1,361 +1,388 @@
1
- <p align="center">
2
- <a href="docs/translations/README.ar.md">العربية</a> •
3
- <a href="docs/translations/README.de.md">Deutsch</a> •
4
- <b>English</b> •
5
- <a href="docs/translations/README.es.md">Español</a> •
6
- <a href="docs/translations/README.fr.md">Français</a> •
7
- <a href="docs/translations/README.it.md">Italiano</a> •
8
- <a href="docs/translations/README.ja.md">日本語</a> •
9
- <a href="docs/translations/README.ko.md">한국어</a> •
10
- <a href="docs/translations/README.nl.md">Nederlands</a> •
11
- <a href="docs/translations/README.pl.md">Polski</a> •
12
- <a href="docs/translations/README.pt-BR.md">Português (BR)</a> •
13
- <a href="docs/translations/README.ru.md">Русский</a> •
14
- <a href="docs/translations/README.tr.md">Türkçe</a> •
15
- <a href="docs/translations/README.zh-CN.md">简体中文</a>
16
- </p>
17
-
18
- <h1>
19
- <img src="https://escalated.dev/apple-touch-icon.png" width="28" style="vertical-align:middle;" />
20
- Escalated
21
- </h1>
22
-
23
- [![Tests](https://github.com/escalated-dev/escalated/actions/workflows/run-tests.yml/badge.svg)](https://github.com/escalated-dev/escalated/actions/workflows/run-tests.yml)
24
- [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B62107%2Fgithub.com%2Fescalated-dev%2Fescalated.svg?type=shield)](https://app.fossa.com/projects/custom%2B62107%2Fgithub.com%2Fescalated-dev%2Fescalated?ref=badge_shield)
25
- [![npm](https://img.shields.io/npm/v/@escalated-dev/escalated)](https://www.npmjs.com/package/@escalated-dev/escalated)
26
- [![Vue 3](https://img.shields.io/badge/vue-3.x-4FC08D?logo=vue.js&logoColor=white)](https://vuejs.org/)
27
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
28
-
29
- <p align="center">
30
- <img src=".github/profile/demo.gif" alt="Escalated demo: filing a ticket and replying from the agent inbox" width="800" />
31
- </p>
32
-
33
- Escalated is an embeddable support ticket system with SLA tracking, escalation rules, agent workflows, and a customer portal. This repo contains all the shared frontend assets (Vue 3 + Inertia.js) used across every supported backend framework.
34
-
35
- 👉 **Learn more, view demos, and compare Cloud vs Self-Hosted options at** **[https://escalated.dev](https://escalated.dev)**
36
-
37
- **You don't install this package directly.** Start with the backend package for your framework — it handles everything including pulling in these frontend assets.
38
-
39
- ## Features
40
-
41
- - **Ticket splitting** — Split a reply into a new standalone ticket while preserving context
42
- - **Ticket snooze** — Snooze tickets with presets (1h, 4h, tomorrow, next week) and automatic wake
43
- - **Saved views / custom queues** — Save, name, and share filter presets as reusable ticket views
44
- - **Embeddable support widget** — Drop-in `<script>` widget with KB search, ticket form, and status check
45
- - **Real-time updates** — WebSocket support (Pusher/Reverb/Soketi) with automatic polling fallback
46
- - **Knowledge base toggle** — Enable or disable the public knowledge base from admin settings
47
- - **CI: ESLint + Prettier** — Automated code style enforcement on every pull request
48
-
49
- ## Get Started
50
-
51
- Pick your framework:
52
-
53
- | Framework | Repo | Install |
54
- |-----------|------|---------|
55
- | **Laravel** | [escalated-dev/escalated-laravel](https://github.com/escalated-dev/escalated-laravel) | `composer require escalated-dev/escalated-laravel` |
56
- | **Rails** | [escalated-dev/escalated-rails](https://github.com/escalated-dev/escalated-rails) | `gem "escalated"` |
57
- | **Django** | [escalated-dev/escalated-django](https://github.com/escalated-dev/escalated-django) | `pip install escalated-django` |
58
- | **AdonisJS** | [escalated-dev/escalated-adonis](https://github.com/escalated-dev/escalated-adonis) | `npm install @escalated-dev/escalated-adonis` |
59
- | **WordPress** | [escalated-dev/escalated-wordpress](https://github.com/escalated-dev/escalated-wordpress) | [Download escalated.zip](https://github.com/escalated-dev/escalated-wordpress/releases/latest) |
60
- | **Filament** | [escalated-dev/escalated-filament](https://github.com/escalated-dev/escalated-filament) | `composer require escalated-dev/escalated-filament` |
61
- | **React Native** | [escalated-dev/escalated-react-native](https://github.com/escalated-dev/escalated-react-native) | `npm install @escalated-dev/escalated-react-native` |
62
- | **Flutter** | [escalated-dev/escalated-flutter](https://github.com/escalated-dev/escalated-flutter) | See [pubspec.yaml setup](https://github.com/escalated-dev/escalated-flutter#quick-start) |
63
-
64
- Each backend repo has full setup instructions — install command, migrations, config, and frontend integration.
65
-
66
- ## Tailwind CSS
67
-
68
- Escalated components use Tailwind CSS classes. You **must** add this package to your Tailwind `content` config so its classes aren't purged:
69
-
70
- ```js
71
- // tailwind.config.js
72
- export default {
73
- content: [
74
- // ... your existing paths
75
- './node_modules/@escalated-dev/escalated/src/**/*.vue',
76
- ],
77
- }
78
- ```
79
-
80
- Without this, Escalated UI will render but styles like button backgrounds and badge colors will be missing.
81
-
82
- ## Theming
83
-
84
- Escalated renders inside a standalone layout by default. To integrate it into your app's design system, use the `EscalatedPlugin`:
85
-
86
- ```js
87
- import { createApp } from 'vue'
88
- import { EscalatedPlugin } from '@escalated-dev/escalated'
89
- import AppLayout from '@/Layouts/AppLayout.vue'
90
-
91
- const app = createApp(...)
92
-
93
- app.use(EscalatedPlugin, {
94
- layout: AppLayout,
95
- theme: {
96
- primary: '#3b82f6',
97
- radius: '0.75rem',
98
- }
99
- })
100
- ```
101
-
102
- ### Layout Integration
103
-
104
- Pass your app's layout component and all Escalated pages render inside it automatically. The layout component must accept a `#header` slot and a default slot:
105
-
106
- ```vue
107
- <!-- Your layout must support these slots -->
108
- <template>
109
- <div>
110
- <nav>...</nav>
111
- <header><slot name="header" /></header>
112
- <main><slot /></main>
113
- </div>
114
- </template>
115
- ```
116
-
117
- When no layout is provided, Escalated uses its own built-in navigation bar.
118
-
119
- ### CSS Custom Properties
120
-
121
- The `theme` option sets CSS custom properties you can reference in your own styles:
122
-
123
- | Property | Default | Description |
124
- |----------|---------|-------------|
125
- | `--esc-primary` | `#4f46e5` | Primary action color |
126
- | `--esc-primary-hover` | auto-darkened | Primary hover color |
127
- | `--esc-radius` | `0.5rem` | Border radius for inputs and buttons |
128
- | `--esc-radius-lg` | auto-scaled | Border radius for cards and panels |
129
- | `--esc-font-family` | inherit | Font family override |
130
-
131
- ### Framework Examples
132
-
133
- **Laravel** (Inertia + Vue 3):
134
- ```js
135
- import { EscalatedPlugin } from '@escalated-dev/escalated'
136
- import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue'
137
-
138
- app.use(EscalatedPlugin, { layout: AuthenticatedLayout })
139
- ```
140
-
141
- **Rails** (Inertia + Vue 3):
142
- ```js
143
- import { EscalatedPlugin } from '@escalated-dev/escalated'
144
- import AppLayout from '@/layouts/AppLayout.vue'
145
-
146
- app.use(EscalatedPlugin, { layout: AppLayout })
147
- ```
148
-
149
- **Django** (Inertia + Vue 3):
150
- ```js
151
- import { EscalatedPlugin } from '@escalated-dev/escalated'
152
- import BaseLayout from '@/layouts/BaseLayout.vue'
153
-
154
- app.use(EscalatedPlugin, { layout: BaseLayout })
155
- ```
156
-
157
- **AdonisJS** (Inertia + Vue 3):
158
- ```js
159
- import { EscalatedPlugin } from '@escalated-dev/escalated'
160
- import AppLayout from '@/layouts/AppLayout.vue'
161
-
162
- app.use(EscalatedPlugin, { layout: AppLayout })
163
- ```
164
-
165
- ## What's in This Repo
166
-
167
- All the Vue 3 + Inertia.js components that power the Escalated UI. These are identical across Laravel, Rails, Django, and AdonisJS — the backend framework renders them via Inertia.
168
-
169
- ## 📸 Screenshots
170
-
171
- > Screenshots are auto-generated from Storybook via the [component-screenshots](.github/workflows/screenshots.yml) workflow.
172
-
173
- <p align="center">
174
- <strong>Admin Panel (Dark)</strong><br/>
175
- <img src="docs/assets/escalated_admin_1.png" alt="Escalated Admin Panel — dark mode with sidebar navigation, KPI cards, stats, and ticket list" width="800" />
176
- </p>
177
-
178
- <p align="center">
179
- <strong>Admin Panel (Light)</strong><br/>
180
- <img src="docs/assets/escalated_admin_3.png" alt="Escalated Admin Panel — light mode with sidebar navigation, KPI cards, stats, and ticket list" width="800" />
181
- </p>
182
-
183
- <p align="center">
184
- <strong>Ticket Queue</strong><br/>
185
- <img src="docs/assets/escalated_ticket_list.png" alt="Escalated Ticket Queue — agent ticket list with filters, search, bulk actions, and SLA indicators" width="800" />
186
- </p>
187
-
188
- <p align="center">
189
- <strong>Agent Panel</strong><br/>
190
- <img src="docs/assets/escalated_admin_2.png" alt="Escalated Agent Panel — top navigation, stats, and assigned ticket queue" width="800" />
191
- </p>
192
-
193
- <p align="center">
194
- <strong>Ticket Detail View</strong><br/>
195
- <img src="docs/assets/escalated_ticket_view.png" alt="Escalated Ticket Detail View — conversation thread, reply composer, and ticket sidebar with SLA timer" width="800" />
196
- </p>
197
-
198
- ### Pages
199
-
200
- **Customer Portal** — Self-service ticket management
201
- - `pages/Customer/Index.vue` — Ticket list with status filters and search
202
- - `pages/Customer/Create.vue` — New ticket form with file attachments
203
- - `pages/Customer/Show.vue` — Ticket detail with reply thread
204
-
205
- **Agent Dashboard** — Ticket queue and workflows
206
- - `pages/Agent/Dashboard.vue` — Stats overview and recent tickets
207
- - `pages/Agent/TicketIndex.vue` — Filterable ticket queue
208
- - `pages/Agent/TicketShow.vue` — Full ticket view with sidebar, internal notes, canned responses
209
-
210
- **Admin Panel** — System configuration
211
- - `pages/Admin/Reports.vue` — Analytics dashboard
212
- - `pages/Admin/Departments/` — Department CRUD
213
- - `pages/Admin/SlaPolicies/` — SLA policy management
214
- - `pages/Admin/EscalationRules/` — Escalation rule builder
215
- - `pages/Admin/Tags/` — Tag management
216
- - `pages/Admin/CannedResponses/` — Canned response templates
217
-
218
- ### Shared Components
219
-
220
- Reusable building blocks used across the pages above.
221
-
222
- | Component | Description |
223
- |-----------|-------------|
224
- | `StatusBadge` | Colored badge for ticket status |
225
- | `PriorityBadge` | Colored badge for ticket priority |
226
- | `TicketList` | Paginated ticket table |
227
- | `ReplyThread` | Chronological reply display |
228
- | `ReplyComposer` | Reply/note editor with file upload and canned response insertion |
229
- | `ActivityTimeline` | Audit log of ticket events |
230
- | `SlaTimer` | SLA countdown with breach/warning states |
231
- | `TicketFilters` | Status, priority, agent, department filter bar |
232
- | `TicketSidebar` | Ticket detail sidebar (status, SLA, tags, activity) |
233
- | `AssigneeSelect` | Agent assignment dropdown |
234
- | `TagSelect` | Multi-select tag picker |
235
- | `FileDropzone` | Drag-and-drop file upload |
236
- | `AttachmentList` | File attachment display with download links |
237
- | `StatsCard` | Metric card with label, value, and trend |
238
- | `EscalatedLayout` | Top-level layout with navigation (supports host layout injection) |
239
- | `BulkActionBar` | Toolbar for batch operations on selected tickets |
240
- | `QuickFilters` | One-click filter chips (My Tickets, Unassigned, Urgent, SLA Breaching) |
241
- | `MacroDropdown` | Dropdown to apply multi-step macros to a ticket |
242
- | `FollowButton` | Toggle button to follow/unfollow a ticket |
243
- | `SatisfactionRating` | 1-5 star CSAT rating input with optional comment |
244
- | `KeyboardShortcutHelp` | Modal overlay showing all available keyboard shortcuts |
245
- | `PinnedNotes` | Display pinned internal notes at the top of the thread |
246
- | `PresenceIndicator` | Real-time indicator showing who is viewing a ticket |
247
-
248
- ### Composables
249
-
250
- | Composable | Description |
251
- |------------|-------------|
252
- | `useKeyboardShortcuts` | Registers and manages keyboard shortcuts for ticket actions |
253
-
254
- ### Plugin
255
-
256
- | Export | Description |
257
- |--------|-------------|
258
- | `EscalatedPlugin` | Vue plugin for layout injection and CSS theming |
259
-
260
- ## Plugin Development
261
-
262
- Escalated supports framework-agnostic plugins built with the [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk). Plugins are written once in TypeScript and work across all Escalated backends.
263
-
264
- ### How the Frontend Plugin System Works
265
-
266
- The frontend uses `defineEscalatedPlugin()` to register Vue components — custom admin pages, ticket sidebar widgets, or dashboard panels — that are mounted automatically when the plugin is active.
267
-
268
- ```typescript
269
- import { defineEscalatedPlugin } from '@escalated-dev/escalated'
270
- import MySettingsPage from './MySettingsPage.vue'
271
-
272
- export default defineEscalatedPlugin({
273
- name: 'my-plugin',
274
- pages: {
275
- 'admin/my-plugin/settings': MySettingsPage,
276
- },
277
- })
278
- ```
279
-
280
- ### How It Connects to the Backend
281
-
282
- The backend uses `definePlugin()` from the [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk) to handle TypeScript business logic — subscribing to ticket lifecycle hooks, exposing API endpoints, and persisting data. The frontend and backend entries work together as a single npm package.
283
-
284
- ```typescript
285
- // backend entry (index.ts)
286
- import { definePlugin } from '@escalated-dev/plugin-sdk'
287
-
288
- export default definePlugin({
289
- name: 'my-plugin',
290
- version: '1.0.0',
291
- actions: {
292
- 'ticket.created': async (event, ctx) => {
293
- ctx.log.info('New ticket!', event)
294
- },
295
- },
296
- })
297
- ```
298
-
299
- ### Quick Example: Both Entry Points
300
-
301
- A published plugin package typically exports both:
302
-
303
- ```
304
- my-plugin/
305
- index.ts ← backend: definePlugin() for TypeScript logic
306
- frontend.ts ← frontend: defineEscalatedPlugin() for Vue components
307
- ```
308
-
309
- The backend framework (Laravel, Rails, Django, AdonisJS) loads `index.ts` via the [Plugin Runtime](https://github.com/escalated-dev/escalated-plugin-runtime). The Vue app imports `frontend.ts` and registers it with `app.use()`.
310
-
311
- ### Installing Plugins
312
-
313
- ```bash
314
- npm install @escalated-dev/plugin-slack
315
- npm install @escalated-dev/plugin-jira
316
- ```
317
-
318
- ### Resources
319
-
320
- - [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk) — TypeScript SDK for building plugins
321
- - [Plugin Runtime](https://github.com/escalated-dev/escalated-plugin-runtime) — Runtime host for plugins
322
- - [Plugin Development Guide](https://github.com/escalated-dev/escalated-docs) — Full documentation
323
-
324
- ## For Package Maintainers
325
-
326
- If you're building a new backend integration, this package is available on npm:
327
-
328
- ```bash
329
- npm install @escalated-dev/escalated
330
- ```
331
-
332
- ```js
333
- // Import the plugin
334
- import { EscalatedPlugin } from '@escalated-dev/escalated'
335
-
336
- // Import individual components
337
- import { StatusBadge, SlaTimer } from '@escalated-dev/escalated'
338
-
339
- // Or reference pages directly for Inertia resolution
340
- import CustomerIndex from '@escalated-dev/escalated/pages/Customer/Index.vue'
341
- ```
342
-
343
- Peer dependencies: `vue` ^3.3.0, `@inertiajs/vue3` ^1.0.0 || ^2.0.0
344
-
345
- ## Ecosystem
346
-
347
- This is the shared frontend for the Escalated support ticket system. Host framework packages and client SDKs available across the ecosystem:
348
-
349
- - **[Escalated for Laravel](https://github.com/escalated-dev/escalated-laravel)** — Laravel Composer package
350
- - **[Escalated for Rails](https://github.com/escalated-dev/escalated-rails)** — Ruby on Rails engine
351
- - **[Escalated for Django](https://github.com/escalated-dev/escalated-django)** — Django reusable app
352
- - **[Escalated for AdonisJS](https://github.com/escalated-dev/escalated-adonis)** — AdonisJS v6 package
353
- - **[Escalated for WordPress](https://github.com/escalated-dev/escalated-wordpress)** — WordPress plugin
354
- - **[Escalated for Filament](https://github.com/escalated-dev/escalated-filament)** — Filament v3 admin panel plugin
355
- - **[Escalated for React Native](https://github.com/escalated-dev/escalated-react-native)** — React Native SDK
356
- - **[Escalated for Flutter](https://github.com/escalated-dev/escalated-flutter)** — Flutter SDK
357
- - **[Shared Frontend](https://github.com/escalated-dev/escalated)** — Vue 3 + Inertia.js UI components (you are here)
358
-
359
- ## License
360
-
361
- MIT
1
+ <p align="center">
2
+ <a href="docs/translations/README.ar.md">العربية</a> •
3
+ <a href="docs/translations/README.de.md">Deutsch</a> •
4
+ <b>English</b> •
5
+ <a href="docs/translations/README.es.md">Español</a> •
6
+ <a href="docs/translations/README.fr.md">Français</a> •
7
+ <a href="docs/translations/README.it.md">Italiano</a> •
8
+ <a href="docs/translations/README.ja.md">日本語</a> •
9
+ <a href="docs/translations/README.ko.md">한국어</a> •
10
+ <a href="docs/translations/README.nl.md">Nederlands</a> •
11
+ <a href="docs/translations/README.pl.md">Polski</a> •
12
+ <a href="docs/translations/README.pt-BR.md">Português (BR)</a> •
13
+ <a href="docs/translations/README.ru.md">Русский</a> •
14
+ <a href="docs/translations/README.tr.md">Türkçe</a> •
15
+ <a href="docs/translations/README.zh-CN.md">简体中文</a>
16
+ </p>
17
+
18
+ <h1 align="center">
19
+ <img src="https://escalated.dev/apple-touch-icon.png" width="28" style="vertical-align:middle;" />
20
+ Escalated
21
+ </h1>
22
+
23
+ <div align="center">
24
+
25
+ [![Tests](https://github.com/escalated-dev/escalated/actions/workflows/run-tests.yml/badge.svg)](https://github.com/escalated-dev/escalated/actions/workflows/run-tests.yml)[![npm](https://img.shields.io/npm/v/@escalated-dev/escalated)](https://www.npmjs.com/package/@escalated-dev/escalated)
26
+ [![Vue 3](https://img.shields.io/badge/vue-3.x-4FC08D?logo=vue.js&logoColor=white)](https://vuejs.org/)
27
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
28
+
29
+ </div>
30
+
31
+ <p align="center">
32
+ <a href="https://escalated.dev">
33
+ <img src=".github/og.png" alt="Escalated — support tickets, built into your app" width="840" />
34
+ </a>
35
+ </p>
36
+
37
+ Escalated is an embeddable support ticket system with SLA tracking, escalation rules, agent workflows, and a customer portal. This repo contains all the shared frontend assets (Vue 3 + Inertia.js) used across every supported backend framework.
38
+
39
+ 👉 **Learn more, view demos, and compare Cloud vs Self-Hosted options at** **[https://escalated.dev](https://escalated.dev)**
40
+
41
+ **You don't install this package directly.** Start with the backend package for your framework — it handles everything including pulling in these frontend assets.
42
+
43
+ <p align="center">
44
+ <img src=".github/profile/demo.gif" alt="Escalated demo: filing a ticket and replying from the agent inbox" width="800" />
45
+ </p>
46
+
47
+ ## Features
48
+
49
+ - **Ticket splitting** — Split a reply into a new standalone ticket while preserving context
50
+ - **Ticket snooze** — Snooze tickets with presets (1h, 4h, tomorrow, next week) and automatic wake
51
+ - **Saved views / custom queues** — Save, name, and share filter presets as reusable ticket views
52
+ - **Embeddable support widget** — Drop-in `<script>` widget with KB search, ticket form, and status check
53
+ - **Real-time updates** — WebSocket support (Pusher/Reverb/Soketi) with automatic polling fallback
54
+ - **Knowledge base toggle** — Enable or disable the public knowledge base from admin settings
55
+ - **CI: ESLint + Prettier** — Automated code style enforcement on every pull request
56
+
57
+ ## Get Started
58
+
59
+ Pick your framework:
60
+
61
+ | Framework | Repo | Install |
62
+ |-----------|------|---------|
63
+ | **Laravel** | [escalated-dev/escalated-laravel](https://github.com/escalated-dev/escalated-laravel) | `composer require escalated-dev/escalated-laravel` |
64
+ | **Rails** | [escalated-dev/escalated-rails](https://github.com/escalated-dev/escalated-rails) | `gem "escalated"` |
65
+ | **Django** | [escalated-dev/escalated-django](https://github.com/escalated-dev/escalated-django) | `pip install escalated-django` |
66
+ | **AdonisJS** | [escalated-dev/escalated-adonis](https://github.com/escalated-dev/escalated-adonis) | `npm install @escalated-dev/escalated-adonis` |
67
+ | **WordPress** | [escalated-dev/escalated-wordpress](https://github.com/escalated-dev/escalated-wordpress) | [Download escalated.zip](https://github.com/escalated-dev/escalated-wordpress/releases/latest) |
68
+ | **Filament** | [escalated-dev/escalated-filament](https://github.com/escalated-dev/escalated-filament) | `composer require escalated-dev/escalated-filament` |
69
+ | **React Native** | [escalated-dev/escalated-react-native](https://github.com/escalated-dev/escalated-react-native) | `npm install @escalated-dev/escalated-react-native` |
70
+ | **Flutter** | [escalated-dev/escalated-flutter](https://github.com/escalated-dev/escalated-flutter) | See [pubspec.yaml setup](https://github.com/escalated-dev/escalated-flutter#quick-start) |
71
+
72
+ Each backend repo has full setup instructions — install command, migrations, config, and frontend integration.
73
+
74
+ ## Tailwind CSS
75
+
76
+ Escalated components use Tailwind CSS utility classes (~hundreds of them across 140+ Vue files). **Some Tailwind-compatible class processor must be available in the host app for the UI to render correctly** — without one, every component renders as unstyled DOM with class names that don't resolve to any CSS.
77
+
78
+ ### Recommended: Tailwind in your existing build
79
+
80
+ If your host app already uses Tailwind via Vite / PostCSS / Tailwind CLI, just add this package to your `content` config so its classes aren't purged:
81
+
82
+ ```js
83
+ // tailwind.config.js
84
+ export default {
85
+ content: [
86
+ // ... your existing paths
87
+ './node_modules/@escalated-dev/escalated/src/**/*.vue',
88
+ ],
89
+ }
90
+ ```
91
+
92
+ > **Tailwind 4+ users:** `content` globs are auto-detected from imported modules — you usually don't need to add anything. Skip this step if you're on v4.
93
+
94
+ ### Using Escalated without a Tailwind build step
95
+
96
+ If you don't want a Tailwind toolchain in your build pipeline, you have a few options. Each has trade-offs — pick the one closest to your project's constraints:
97
+
98
+ | Option | When to use | How |
99
+ |---|---|---|
100
+ | **Tailwind Play CDN** | Prototyping, internal tools, demos. Not recommended for production (no purging, ~3 MB script tag). | Add `<script src="https://cdn.tailwindcss.com"></script>` to the page that renders Escalated. The CDN script JIT-compiles classes at runtime. |
101
+ | **Tailwind standalone CLI** | You want a static stylesheet without npm/Vite. | Download the [standalone CLI binary](https://tailwindcss.com/blog/standalone-cli) and run `tailwindcss -i input.css -o public/escalated.css --content './node_modules/@escalated-dev/escalated/src/**/*.vue' --minify`. Link the output stylesheet from your page. |
102
+ | **UnoCSS / Twind in attributify mode** | Already using one of these atomic-CSS engines. | Configure with the Tailwind preset (`@unocss/preset-wind` or `@twind/preset-tailwind`) and add the Escalated package path to the engine's scan config. Class semantics match. |
103
+ | **Forking with hand-rolled CSS** | You categorically cannot ship any Tailwind-compatible tooling and are willing to maintain a fork. | Replace utility classes with scoped CSS per component. Substantial effort; not officially supported. |
104
+
105
+ If none of these fit, please [open a discussion](https://github.com/escalated-dev/escalated/discussions) so we can understand the constraint and consider a pre-compiled CSS distribution.
106
+
107
+ Whatever path you choose, also make sure the [theme tokens](#theming) (CSS custom properties) are applied — those control colour, spacing, and radius and are independent of Tailwind.
108
+
109
+ ## Theming
110
+
111
+ Escalated renders inside a standalone layout by default. To integrate it into your app's design system, use the `EscalatedPlugin`:
112
+
113
+ ```js
114
+ import { createApp } from 'vue'
115
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
116
+ import AppLayout from '@/Layouts/AppLayout.vue'
117
+
118
+ const app = createApp(...)
119
+
120
+ app.use(EscalatedPlugin, {
121
+ layout: AppLayout,
122
+ theme: {
123
+ primary: '#3b82f6',
124
+ radius: '0.75rem',
125
+ }
126
+ })
127
+ ```
128
+
129
+ ### Layout Integration
130
+
131
+ Pass your app's layout component and all Escalated pages render inside it automatically. The layout component must accept a `#header` slot and a default slot:
132
+
133
+ ```vue
134
+ <!-- Your layout must support these slots -->
135
+ <template>
136
+ <div>
137
+ <nav>...</nav>
138
+ <header><slot name="header" /></header>
139
+ <main><slot /></main>
140
+ </div>
141
+ </template>
142
+ ```
143
+
144
+ When no layout is provided, Escalated uses its own built-in navigation bar.
145
+
146
+ ### CSS Custom Properties
147
+
148
+ The `theme` option sets CSS custom properties you can reference in your own styles:
149
+
150
+ | Property | Default | Description |
151
+ |----------|---------|-------------|
152
+ | `--esc-primary` | `#4f46e5` | Primary action color |
153
+ | `--esc-primary-hover` | auto-darkened | Primary hover color |
154
+ | `--esc-radius` | `0.5rem` | Border radius for inputs and buttons |
155
+ | `--esc-radius-lg` | auto-scaled | Border radius for cards and panels |
156
+ | `--esc-font-family` | inherit | Font family override |
157
+
158
+ ### Framework Examples
159
+
160
+ **Laravel** (Inertia + Vue 3):
161
+ ```js
162
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
163
+ import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue'
164
+
165
+ app.use(EscalatedPlugin, { layout: AuthenticatedLayout })
166
+ ```
167
+
168
+ **Rails** (Inertia + Vue 3):
169
+ ```js
170
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
171
+ import AppLayout from '@/layouts/AppLayout.vue'
172
+
173
+ app.use(EscalatedPlugin, { layout: AppLayout })
174
+ ```
175
+
176
+ **Django** (Inertia + Vue 3):
177
+ ```js
178
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
179
+ import BaseLayout from '@/layouts/BaseLayout.vue'
180
+
181
+ app.use(EscalatedPlugin, { layout: BaseLayout })
182
+ ```
183
+
184
+ **AdonisJS** (Inertia + Vue 3):
185
+ ```js
186
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
187
+ import AppLayout from '@/layouts/AppLayout.vue'
188
+
189
+ app.use(EscalatedPlugin, { layout: AppLayout })
190
+ ```
191
+
192
+ ## What's in This Repo
193
+
194
+ All the Vue 3 + Inertia.js components that power the Escalated UI. These are identical across Laravel, Rails, Django, and AdonisJS — the backend framework renders them via Inertia.
195
+
196
+ ## 📸 Screenshots
197
+
198
+ > Screenshots are auto-generated from Storybook via the [component-screenshots](.github/workflows/screenshots.yml) workflow.
199
+
200
+ <p align="center">
201
+ <strong>Admin Panel (Dark)</strong><br/>
202
+ <img src="docs/assets/escalated_admin_1.png" alt="Escalated Admin Panel — dark mode with sidebar navigation, KPI cards, stats, and ticket list" width="800" />
203
+ </p>
204
+
205
+ <p align="center">
206
+ <strong>Admin Panel (Light)</strong><br/>
207
+ <img src="docs/assets/escalated_admin_3.png" alt="Escalated Admin Panel — light mode with sidebar navigation, KPI cards, stats, and ticket list" width="800" />
208
+ </p>
209
+
210
+ <p align="center">
211
+ <strong>Ticket Queue</strong><br/>
212
+ <img src="docs/assets/escalated_ticket_list.png" alt="Escalated Ticket Queue — agent ticket list with filters, search, bulk actions, and SLA indicators" width="800" />
213
+ </p>
214
+
215
+ <p align="center">
216
+ <strong>Agent Panel</strong><br/>
217
+ <img src="docs/assets/escalated_admin_2.png" alt="Escalated Agent Panel — top navigation, stats, and assigned ticket queue" width="800" />
218
+ </p>
219
+
220
+ <p align="center">
221
+ <strong>Ticket Detail View</strong><br/>
222
+ <img src="docs/assets/escalated_ticket_view.png" alt="Escalated Ticket Detail View — conversation thread, reply composer, and ticket sidebar with SLA timer" width="800" />
223
+ </p>
224
+
225
+ ### Pages
226
+
227
+ **Customer Portal** — Self-service ticket management
228
+ - `pages/Customer/Index.vue` — Ticket list with status filters and search
229
+ - `pages/Customer/Create.vue` — New ticket form with file attachments
230
+ - `pages/Customer/Show.vue` — Ticket detail with reply thread
231
+
232
+ **Agent Dashboard** — Ticket queue and workflows
233
+ - `pages/Agent/Dashboard.vue` — Stats overview and recent tickets
234
+ - `pages/Agent/TicketIndex.vue` — Filterable ticket queue
235
+ - `pages/Agent/TicketShow.vue` — Full ticket view with sidebar, internal notes, canned responses
236
+
237
+ **Admin Panel** — System configuration
238
+ - `pages/Admin/Reports.vue` — Analytics dashboard
239
+ - `pages/Admin/Departments/` — Department CRUD
240
+ - `pages/Admin/SlaPolicies/` — SLA policy management
241
+ - `pages/Admin/EscalationRules/` — Escalation rule builder
242
+ - `pages/Admin/Tags/` — Tag management
243
+ - `pages/Admin/CannedResponses/` — Canned response templates
244
+
245
+ ### Shared Components
246
+
247
+ Reusable building blocks used across the pages above.
248
+
249
+ | Component | Description |
250
+ |-----------|-------------|
251
+ | `StatusBadge` | Colored badge for ticket status |
252
+ | `PriorityBadge` | Colored badge for ticket priority |
253
+ | `TicketList` | Paginated ticket table |
254
+ | `ReplyThread` | Chronological reply display |
255
+ | `ReplyComposer` | Reply/note editor with file upload and canned response insertion |
256
+ | `ActivityTimeline` | Audit log of ticket events |
257
+ | `SlaTimer` | SLA countdown with breach/warning states |
258
+ | `TicketFilters` | Status, priority, agent, department filter bar |
259
+ | `TicketSidebar` | Ticket detail sidebar (status, SLA, tags, activity) |
260
+ | `AssigneeSelect` | Agent assignment dropdown |
261
+ | `TagSelect` | Multi-select tag picker |
262
+ | `FileDropzone` | Drag-and-drop file upload |
263
+ | `AttachmentList` | File attachment display with download links |
264
+ | `StatsCard` | Metric card with label, value, and trend |
265
+ | `EscalatedLayout` | Top-level layout with navigation (supports host layout injection) |
266
+ | `BulkActionBar` | Toolbar for batch operations on selected tickets |
267
+ | `QuickFilters` | One-click filter chips (My Tickets, Unassigned, Urgent, SLA Breaching) |
268
+ | `MacroDropdown` | Dropdown to apply multi-step macros to a ticket |
269
+ | `FollowButton` | Toggle button to follow/unfollow a ticket |
270
+ | `SatisfactionRating` | 1-5 star CSAT rating input with optional comment |
271
+ | `KeyboardShortcutHelp` | Modal overlay showing all available keyboard shortcuts |
272
+ | `PinnedNotes` | Display pinned internal notes at the top of the thread |
273
+ | `PresenceIndicator` | Real-time indicator showing who is viewing a ticket |
274
+
275
+ ### Composables
276
+
277
+ | Composable | Description |
278
+ |------------|-------------|
279
+ | `useKeyboardShortcuts` | Registers and manages keyboard shortcuts for ticket actions |
280
+
281
+ ### Plugin
282
+
283
+ | Export | Description |
284
+ |--------|-------------|
285
+ | `EscalatedPlugin` | Vue plugin for layout injection and CSS theming |
286
+
287
+ ## Plugin Development
288
+
289
+ Escalated supports framework-agnostic plugins built with the [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk). Plugins are written once in TypeScript and work across all Escalated backends.
290
+
291
+ ### How the Frontend Plugin System Works
292
+
293
+ The frontend uses `defineEscalatedPlugin()` to register Vue components — custom admin pages, ticket sidebar widgets, or dashboard panels — that are mounted automatically when the plugin is active.
294
+
295
+ ```typescript
296
+ import { defineEscalatedPlugin } from '@escalated-dev/escalated'
297
+ import MySettingsPage from './MySettingsPage.vue'
298
+
299
+ export default defineEscalatedPlugin({
300
+ name: 'my-plugin',
301
+ pages: {
302
+ 'admin/my-plugin/settings': MySettingsPage,
303
+ },
304
+ })
305
+ ```
306
+
307
+ ### How It Connects to the Backend
308
+
309
+ The backend uses `definePlugin()` from the [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk) to handle TypeScript business logic — subscribing to ticket lifecycle hooks, exposing API endpoints, and persisting data. The frontend and backend entries work together as a single npm package.
310
+
311
+ ```typescript
312
+ // backend entry (index.ts)
313
+ import { definePlugin } from '@escalated-dev/plugin-sdk'
314
+
315
+ export default definePlugin({
316
+ name: 'my-plugin',
317
+ version: '1.0.0',
318
+ actions: {
319
+ 'ticket.created': async (event, ctx) => {
320
+ ctx.log.info('New ticket!', event)
321
+ },
322
+ },
323
+ })
324
+ ```
325
+
326
+ ### Quick Example: Both Entry Points
327
+
328
+ A published plugin package typically exports both:
329
+
330
+ ```
331
+ my-plugin/
332
+ index.ts ← backend: definePlugin() for TypeScript logic
333
+ frontend.ts ← frontend: defineEscalatedPlugin() for Vue components
334
+ ```
335
+
336
+ The backend framework (Laravel, Rails, Django, AdonisJS) loads `index.ts` via the [Plugin Runtime](https://github.com/escalated-dev/escalated-plugin-runtime). The Vue app imports `frontend.ts` and registers it with `app.use()`.
337
+
338
+ ### Installing Plugins
339
+
340
+ ```bash
341
+ npm install @escalated-dev/plugin-slack
342
+ npm install @escalated-dev/plugin-jira
343
+ ```
344
+
345
+ ### Resources
346
+
347
+ - [Plugin SDK](https://github.com/escalated-dev/escalated-plugin-sdk) — TypeScript SDK for building plugins
348
+ - [Plugin Runtime](https://github.com/escalated-dev/escalated-plugin-runtime) — Runtime host for plugins
349
+ - [Plugin Development Guide](https://github.com/escalated-dev/escalated-docs) — Full documentation
350
+
351
+ ## For Package Maintainers
352
+
353
+ If you're building a new backend integration, this package is available on npm:
354
+
355
+ ```bash
356
+ npm install @escalated-dev/escalated
357
+ ```
358
+
359
+ ```js
360
+ // Import the plugin
361
+ import { EscalatedPlugin } from '@escalated-dev/escalated'
362
+
363
+ // Import individual components
364
+ import { StatusBadge, SlaTimer } from '@escalated-dev/escalated'
365
+
366
+ // Or reference pages directly for Inertia resolution
367
+ import CustomerIndex from '@escalated-dev/escalated/pages/Customer/Index.vue'
368
+ ```
369
+
370
+ Peer dependencies: `vue` ^3.3.0, `@inertiajs/vue3` ^1.0.0 || ^2.0.0
371
+
372
+ ## Ecosystem
373
+
374
+ This is the shared frontend for the Escalated support ticket system. Host framework packages and client SDKs available across the ecosystem:
375
+
376
+ - **[Escalated for Laravel](https://github.com/escalated-dev/escalated-laravel)** — Laravel Composer package
377
+ - **[Escalated for Rails](https://github.com/escalated-dev/escalated-rails)** — Ruby on Rails engine
378
+ - **[Escalated for Django](https://github.com/escalated-dev/escalated-django)** — Django reusable app
379
+ - **[Escalated for AdonisJS](https://github.com/escalated-dev/escalated-adonis)** — AdonisJS v6 package
380
+ - **[Escalated for WordPress](https://github.com/escalated-dev/escalated-wordpress)** — WordPress plugin
381
+ - **[Escalated for Filament](https://github.com/escalated-dev/escalated-filament)** — Filament v3 admin panel plugin
382
+ - **[Escalated for React Native](https://github.com/escalated-dev/escalated-react-native)** — React Native SDK
383
+ - **[Escalated for Flutter](https://github.com/escalated-dev/escalated-flutter)** — Flutter SDK
384
+ - **[Shared Frontend](https://github.com/escalated-dev/escalated)** — Vue 3 + Inertia.js UI components (you are here)
385
+
386
+ ## License
387
+
388
+ MIT