@djangocfg/ext-support 1.0.0
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.
- package/README.md +233 -0
- package/dist/chunk-AZ4LWZB7.js +2630 -0
- package/dist/hooks.cjs +2716 -0
- package/dist/hooks.d.cts +255 -0
- package/dist/hooks.d.ts +255 -0
- package/dist/hooks.js +1 -0
- package/dist/index.cjs +2693 -0
- package/dist/index.d.cts +1392 -0
- package/dist/index.d.ts +1392 -0
- package/dist/index.js +1 -0
- package/package.json +80 -0
- package/src/api/generated/ext_support/_utils/fetchers/ext_support__support.ts +642 -0
- package/src/api/generated/ext_support/_utils/fetchers/index.ts +28 -0
- package/src/api/generated/ext_support/_utils/hooks/ext_support__support.ts +237 -0
- package/src/api/generated/ext_support/_utils/hooks/index.ts +28 -0
- package/src/api/generated/ext_support/_utils/schemas/Message.schema.ts +21 -0
- package/src/api/generated/ext_support/_utils/schemas/MessageCreate.schema.ts +15 -0
- package/src/api/generated/ext_support/_utils/schemas/MessageCreateRequest.schema.ts +15 -0
- package/src/api/generated/ext_support/_utils/schemas/MessageRequest.schema.ts +15 -0
- package/src/api/generated/ext_support/_utils/schemas/PaginatedMessageList.schema.ts +24 -0
- package/src/api/generated/ext_support/_utils/schemas/PaginatedTicketList.schema.ts +24 -0
- package/src/api/generated/ext_support/_utils/schemas/PatchedMessageRequest.schema.ts +15 -0
- package/src/api/generated/ext_support/_utils/schemas/PatchedTicketRequest.schema.ts +18 -0
- package/src/api/generated/ext_support/_utils/schemas/Sender.schema.ts +21 -0
- package/src/api/generated/ext_support/_utils/schemas/Ticket.schema.ts +21 -0
- package/src/api/generated/ext_support/_utils/schemas/TicketRequest.schema.ts +18 -0
- package/src/api/generated/ext_support/_utils/schemas/index.ts +29 -0
- package/src/api/generated/ext_support/api-instance.ts +131 -0
- package/src/api/generated/ext_support/client.ts +301 -0
- package/src/api/generated/ext_support/enums.ts +45 -0
- package/src/api/generated/ext_support/errors.ts +116 -0
- package/src/api/generated/ext_support/ext_support__support/client.ts +151 -0
- package/src/api/generated/ext_support/ext_support__support/index.ts +2 -0
- package/src/api/generated/ext_support/ext_support__support/models.ts +165 -0
- package/src/api/generated/ext_support/http.ts +103 -0
- package/src/api/generated/ext_support/index.ts +273 -0
- package/src/api/generated/ext_support/logger.ts +259 -0
- package/src/api/generated/ext_support/retry.ts +175 -0
- package/src/api/generated/ext_support/schema.json +1049 -0
- package/src/api/generated/ext_support/storage.ts +161 -0
- package/src/api/generated/ext_support/validation-events.ts +133 -0
- package/src/api/index.ts +9 -0
- package/src/config.ts +20 -0
- package/src/contexts/SupportContext.tsx +250 -0
- package/src/contexts/SupportExtensionProvider.tsx +38 -0
- package/src/contexts/types.ts +26 -0
- package/src/hooks/index.ts +33 -0
- package/src/index.ts +39 -0
- package/src/layouts/SupportLayout/README.md +91 -0
- package/src/layouts/SupportLayout/SupportLayout.tsx +179 -0
- package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +155 -0
- package/src/layouts/SupportLayout/components/MessageInput.tsx +92 -0
- package/src/layouts/SupportLayout/components/MessageList.tsx +312 -0
- package/src/layouts/SupportLayout/components/TicketCard.tsx +96 -0
- package/src/layouts/SupportLayout/components/TicketList.tsx +153 -0
- package/src/layouts/SupportLayout/components/index.ts +6 -0
- package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +258 -0
- package/src/layouts/SupportLayout/context/index.ts +2 -0
- package/src/layouts/SupportLayout/events.ts +33 -0
- package/src/layouts/SupportLayout/hooks/index.ts +2 -0
- package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +115 -0
- package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +88 -0
- package/src/layouts/SupportLayout/index.ts +6 -0
- package/src/layouts/SupportLayout/types.ts +21 -0
- package/src/utils/logger.ts +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# @djangocfg/ext-support
|
|
2
|
+
|
|
3
|
+
Customer support and ticketing system extension for DjangoCFG.
|
|
4
|
+
|
|
5
|
+
**Part of [DjangoCFG](https://djangocfg.com)** — modern Django framework for production-ready SaaS applications.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🎫 **Ticket Management** - Create, track, and resolve support tickets
|
|
10
|
+
- 💬 **Real-time Chat** - Live chat support integration
|
|
11
|
+
- 📧 **Email Integration** - Convert emails to tickets automatically
|
|
12
|
+
- 🏷️ **Categories & Tags** - Organize tickets with custom categories
|
|
13
|
+
- 👥 **Team Assignment** - Assign tickets to support agents
|
|
14
|
+
- 📊 **Analytics** - Track response times and resolution rates
|
|
15
|
+
- 🔔 **Notifications** - Real-time ticket updates
|
|
16
|
+
- 📎 **Attachments** - Support for file attachments
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @djangocfg/ext-support
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Provider Setup
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { SupportExtensionProvider } from '@djangocfg/ext-support/hooks';
|
|
30
|
+
|
|
31
|
+
export default function RootLayout({ children }) {
|
|
32
|
+
return (
|
|
33
|
+
<SupportExtensionProvider>
|
|
34
|
+
{children}
|
|
35
|
+
</SupportExtensionProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Create Support Ticket
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
44
|
+
|
|
45
|
+
function ContactSupport() {
|
|
46
|
+
const { createTicket, isCreatingTicket } = useSupportContext();
|
|
47
|
+
|
|
48
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
const formData = new FormData(e.currentTarget);
|
|
51
|
+
|
|
52
|
+
await createTicket({
|
|
53
|
+
subject: formData.get('subject') as string,
|
|
54
|
+
description: formData.get('description') as string,
|
|
55
|
+
category: 'technical',
|
|
56
|
+
priority: 'medium',
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<form onSubmit={handleSubmit}>
|
|
62
|
+
<input name="subject" placeholder="Subject" required />
|
|
63
|
+
<textarea name="description" placeholder="Describe your issue" required />
|
|
64
|
+
<button type="submit" disabled={isCreatingTicket}>
|
|
65
|
+
{isCreatingTicket ? 'Submitting...' : 'Submit Ticket'}
|
|
66
|
+
</button>
|
|
67
|
+
</form>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### View Tickets
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
76
|
+
|
|
77
|
+
function TicketsPage() {
|
|
78
|
+
const { tickets, isLoadingTickets, updateTicket } = useSupportContext();
|
|
79
|
+
|
|
80
|
+
const handleStatusChange = async (ticketId: string, status: string) => {
|
|
81
|
+
await updateTicket(ticketId, { status });
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<h2>Support Tickets</h2>
|
|
87
|
+
{tickets.map(ticket => (
|
|
88
|
+
<div key={ticket.id}>
|
|
89
|
+
<h3>{ticket.subject}</h3>
|
|
90
|
+
<p>{ticket.description}</p>
|
|
91
|
+
<span>Status: {ticket.status}</span>
|
|
92
|
+
<span>Priority: {ticket.priority}</span>
|
|
93
|
+
<select
|
|
94
|
+
value={ticket.status}
|
|
95
|
+
onChange={(e) => handleStatusChange(ticket.id, e.target.value)}
|
|
96
|
+
>
|
|
97
|
+
<option value="open">Open</option>
|
|
98
|
+
<option value="in_progress">In Progress</option>
|
|
99
|
+
<option value="resolved">Resolved</option>
|
|
100
|
+
<option value="closed">Closed</option>
|
|
101
|
+
</select>
|
|
102
|
+
</div>
|
|
103
|
+
))}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Ticket Details with Comments
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
113
|
+
|
|
114
|
+
function TicketDetails({ ticketId }: { ticketId: string }) {
|
|
115
|
+
const { getTicketById, addComment } = useSupportContext();
|
|
116
|
+
const [ticket, setTicket] = useState(null);
|
|
117
|
+
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
getTicketById(ticketId).then(setTicket);
|
|
120
|
+
}, [ticketId]);
|
|
121
|
+
|
|
122
|
+
const handleAddComment = async (text: string) => {
|
|
123
|
+
await addComment(ticketId, {
|
|
124
|
+
text,
|
|
125
|
+
is_internal: false,
|
|
126
|
+
});
|
|
127
|
+
// Refresh ticket
|
|
128
|
+
getTicketById(ticketId).then(setTicket);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (!ticket) return <div>Loading...</div>;
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<div>
|
|
135
|
+
<h2>{ticket.subject}</h2>
|
|
136
|
+
<p>{ticket.description}</p>
|
|
137
|
+
|
|
138
|
+
<div>
|
|
139
|
+
<h3>Comments</h3>
|
|
140
|
+
{ticket.comments?.map(comment => (
|
|
141
|
+
<div key={comment.id}>
|
|
142
|
+
<strong>{comment.author}</strong>
|
|
143
|
+
<p>{comment.text}</p>
|
|
144
|
+
<span>{new Date(comment.created_at).toLocaleString()}</span>
|
|
145
|
+
</div>
|
|
146
|
+
))}
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<textarea
|
|
150
|
+
placeholder="Add a comment..."
|
|
151
|
+
onKeyDown={(e) => {
|
|
152
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
handleAddComment(e.currentTarget.value);
|
|
155
|
+
e.currentTarget.value = '';
|
|
156
|
+
}
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Ticket Filters
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
168
|
+
|
|
169
|
+
function TicketFilters() {
|
|
170
|
+
const { tickets, filterTickets } = useSupportContext();
|
|
171
|
+
|
|
172
|
+
const handleFilter = (status: string) => {
|
|
173
|
+
filterTickets({ status });
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div>
|
|
178
|
+
<button onClick={() => handleFilter('open')}>
|
|
179
|
+
Open ({tickets.filter(t => t.status === 'open').length})
|
|
180
|
+
</button>
|
|
181
|
+
<button onClick={() => handleFilter('in_progress')}>
|
|
182
|
+
In Progress ({tickets.filter(t => t.status === 'in_progress').length})
|
|
183
|
+
</button>
|
|
184
|
+
<button onClick={() => handleFilter('resolved')}>
|
|
185
|
+
Resolved ({tickets.filter(t => t.status === 'resolved').length})
|
|
186
|
+
</button>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## API Reference
|
|
193
|
+
|
|
194
|
+
### Support Context
|
|
195
|
+
|
|
196
|
+
- `tickets` - List of all tickets
|
|
197
|
+
- `createTicket(data)` - Create new ticket
|
|
198
|
+
- `updateTicket(id, data)` - Update ticket
|
|
199
|
+
- `deleteTicket(id)` - Delete ticket
|
|
200
|
+
- `getTicketById(id)` - Get ticket details
|
|
201
|
+
- `addComment(ticketId, data)` - Add comment to ticket
|
|
202
|
+
- `assignTicket(ticketId, agentId)` - Assign ticket to agent
|
|
203
|
+
- `closeTicket(id)` - Close ticket
|
|
204
|
+
- `reopenTicket(id)` - Reopen closed ticket
|
|
205
|
+
- `filterTickets(filters)` - Filter tickets by criteria
|
|
206
|
+
- `isLoadingTickets` - Loading state
|
|
207
|
+
- `isCreatingTicket` - Creation state
|
|
208
|
+
|
|
209
|
+
## Ticket Properties
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface Ticket {
|
|
213
|
+
id: string;
|
|
214
|
+
subject: string;
|
|
215
|
+
description: string;
|
|
216
|
+
status: 'open' | 'in_progress' | 'resolved' | 'closed';
|
|
217
|
+
priority: 'low' | 'medium' | 'high' | 'urgent';
|
|
218
|
+
category: string;
|
|
219
|
+
assigned_to?: string;
|
|
220
|
+
created_at: string;
|
|
221
|
+
updated_at: string;
|
|
222
|
+
comments?: Comment[];
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT
|
|
229
|
+
|
|
230
|
+
## Links
|
|
231
|
+
|
|
232
|
+
- [DjangoCFG Documentation](https://djangocfg.com)
|
|
233
|
+
- [GitHub](https://github.com/markolofsen/django-cfg)
|