@djangocfg/ext-support 1.0.14 → 1.0.17
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 +123 -156
- package/dist/config.cjs +2 -2
- package/dist/config.js +2 -2
- package/dist/hooks.cjs +2 -2
- package/dist/hooks.js +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.js +2 -2
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
**[
|
|
5
|
+
**[View in Marketplace](https://hub.djangocfg.com/extensions/djangocfg-ext-support)** | **[Documentation](https://djangocfg.com)** | **[GitHub](https://github.com/markolofsen/django-cfg)**
|
|
6
6
|
|
|
7
7
|
</div>
|
|
8
8
|
|
|
@@ -14,14 +14,17 @@ Customer support and ticketing system extension for DjangoCFG.
|
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
17
|
+
- Ticket Management - Create, track, and resolve support tickets
|
|
18
|
+
- Real-time Messaging - Live chat within tickets
|
|
19
|
+
- Categories & Priority - Organize tickets efficiently
|
|
20
|
+
- Analytics - Track response times and resolution rates
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Next.js 16+
|
|
25
|
+
- React 19+
|
|
26
|
+
- @djangocfg/ui-core
|
|
27
|
+
- @djangocfg/ext-base
|
|
25
28
|
|
|
26
29
|
## Install
|
|
27
30
|
|
|
@@ -29,169 +32,102 @@ Customer support and ticketing system extension for DjangoCFG.
|
|
|
29
32
|
pnpm add @djangocfg/ext-support
|
|
30
33
|
```
|
|
31
34
|
|
|
32
|
-
##
|
|
35
|
+
## Quick Start (Next.js App Router)
|
|
33
36
|
|
|
34
|
-
###
|
|
37
|
+
### 1. Create layout.tsx (Server Component for metadata)
|
|
35
38
|
|
|
36
39
|
```typescript
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
// app/support/layout.tsx
|
|
41
|
+
import type { Metadata } from 'next';
|
|
42
|
+
|
|
43
|
+
export const metadata: Metadata = {
|
|
44
|
+
title: 'Support',
|
|
45
|
+
description: 'Help and support center',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default function SupportLayout({
|
|
49
|
+
children,
|
|
50
|
+
}: {
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
}) {
|
|
53
|
+
return children;
|
|
45
54
|
}
|
|
46
55
|
```
|
|
47
56
|
|
|
48
|
-
### Create
|
|
57
|
+
### 2. Create page.tsx (Client Component)
|
|
49
58
|
|
|
50
59
|
```typescript
|
|
51
|
-
|
|
60
|
+
// app/support/page.tsx
|
|
61
|
+
'use client';
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
const { createTicket, isCreatingTicket } = useSupportContext();
|
|
55
|
-
|
|
56
|
-
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
57
|
-
e.preventDefault();
|
|
58
|
-
const formData = new FormData(e.currentTarget);
|
|
59
|
-
|
|
60
|
-
await createTicket({
|
|
61
|
-
subject: formData.get('subject') as string,
|
|
62
|
-
description: formData.get('description') as string,
|
|
63
|
-
category: 'technical',
|
|
64
|
-
priority: 'medium',
|
|
65
|
-
});
|
|
66
|
-
};
|
|
63
|
+
import { SupportLayout } from '@djangocfg/ext-support';
|
|
67
64
|
|
|
65
|
+
export default function SupportPage() {
|
|
68
66
|
return (
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<button type="submit" disabled={isCreatingTicket}>
|
|
73
|
-
{isCreatingTicket ? 'Submitting...' : 'Submit Ticket'}
|
|
74
|
-
</button>
|
|
75
|
-
</form>
|
|
67
|
+
<SupportLayout>
|
|
68
|
+
{/* Optional: custom content */}
|
|
69
|
+
</SupportLayout>
|
|
76
70
|
);
|
|
77
71
|
}
|
|
78
72
|
```
|
|
79
73
|
|
|
80
|
-
|
|
74
|
+
That's it! `SupportLayout` includes everything: providers, ticket list, chat panel, and create ticket dialog.
|
|
81
75
|
|
|
82
|
-
|
|
83
|
-
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
76
|
+
## Custom Integration
|
|
84
77
|
|
|
85
|
-
|
|
86
|
-
const { tickets, isLoadingTickets, updateTicket } = useSupportContext();
|
|
78
|
+
If you need more control, use individual components:
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
await updateTicket(ticketId, { status });
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<div>
|
|
94
|
-
<h2>Support Tickets</h2>
|
|
95
|
-
{tickets.map(ticket => (
|
|
96
|
-
<div key={ticket.id}>
|
|
97
|
-
<h3>{ticket.subject}</h3>
|
|
98
|
-
<p>{ticket.description}</p>
|
|
99
|
-
<span>Status: {ticket.status}</span>
|
|
100
|
-
<span>Priority: {ticket.priority}</span>
|
|
101
|
-
<select
|
|
102
|
-
value={ticket.status}
|
|
103
|
-
onChange={(e) => handleStatusChange(ticket.id, e.target.value)}
|
|
104
|
-
>
|
|
105
|
-
<option value="open">Open</option>
|
|
106
|
-
<option value="in_progress">In Progress</option>
|
|
107
|
-
<option value="resolved">Resolved</option>
|
|
108
|
-
<option value="closed">Closed</option>
|
|
109
|
-
</select>
|
|
110
|
-
</div>
|
|
111
|
-
))}
|
|
112
|
-
</div>
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Ticket Details with Comments
|
|
80
|
+
### Provider Setup
|
|
118
81
|
|
|
119
82
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
function TicketDetails({ ticketId }: { ticketId: string }) {
|
|
123
|
-
const { getTicketById, addComment } = useSupportContext();
|
|
124
|
-
const [ticket, setTicket] = useState(null);
|
|
83
|
+
// app/providers.tsx
|
|
84
|
+
'use client';
|
|
125
85
|
|
|
126
|
-
|
|
127
|
-
getTicketById(ticketId).then(setTicket);
|
|
128
|
-
}, [ticketId]);
|
|
129
|
-
|
|
130
|
-
const handleAddComment = async (text: string) => {
|
|
131
|
-
await addComment(ticketId, {
|
|
132
|
-
text,
|
|
133
|
-
is_internal: false,
|
|
134
|
-
});
|
|
135
|
-
// Refresh ticket
|
|
136
|
-
getTicketById(ticketId).then(setTicket);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
if (!ticket) return <div>Loading...</div>;
|
|
86
|
+
import { SupportProvider } from '@djangocfg/ext-support/hooks';
|
|
140
87
|
|
|
88
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
141
89
|
return (
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<div>
|
|
147
|
-
<h3>Comments</h3>
|
|
148
|
-
{ticket.comments?.map(comment => (
|
|
149
|
-
<div key={comment.id}>
|
|
150
|
-
<strong>{comment.author}</strong>
|
|
151
|
-
<p>{comment.text}</p>
|
|
152
|
-
<span>{new Date(comment.created_at).toLocaleString()}</span>
|
|
153
|
-
</div>
|
|
154
|
-
))}
|
|
155
|
-
</div>
|
|
156
|
-
|
|
157
|
-
<textarea
|
|
158
|
-
placeholder="Add a comment..."
|
|
159
|
-
onKeyDown={(e) => {
|
|
160
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
161
|
-
e.preventDefault();
|
|
162
|
-
handleAddComment(e.currentTarget.value);
|
|
163
|
-
e.currentTarget.value = '';
|
|
164
|
-
}
|
|
165
|
-
}}
|
|
166
|
-
/>
|
|
167
|
-
</div>
|
|
90
|
+
<SupportProvider>
|
|
91
|
+
{children}
|
|
92
|
+
</SupportProvider>
|
|
168
93
|
);
|
|
169
94
|
}
|
|
170
95
|
```
|
|
171
96
|
|
|
172
|
-
###
|
|
97
|
+
### Using Context Hooks
|
|
173
98
|
|
|
174
99
|
```typescript
|
|
100
|
+
'use client';
|
|
101
|
+
|
|
175
102
|
import { useSupportContext } from '@djangocfg/ext-support/hooks';
|
|
176
103
|
|
|
177
|
-
function
|
|
178
|
-
const {
|
|
104
|
+
function MyTicketList() {
|
|
105
|
+
const {
|
|
106
|
+
tickets,
|
|
107
|
+
isLoadingTickets,
|
|
108
|
+
createTicket,
|
|
109
|
+
refreshTickets
|
|
110
|
+
} = useSupportContext();
|
|
179
111
|
|
|
180
|
-
const
|
|
181
|
-
|
|
112
|
+
const handleCreate = async () => {
|
|
113
|
+
await createTicket({
|
|
114
|
+
subject: 'New ticket',
|
|
115
|
+
message: 'Description here',
|
|
116
|
+
});
|
|
117
|
+
await refreshTickets();
|
|
182
118
|
};
|
|
183
119
|
|
|
120
|
+
if (isLoadingTickets) return <div>Loading...</div>;
|
|
121
|
+
|
|
184
122
|
return (
|
|
185
123
|
<div>
|
|
186
|
-
<button onClick={
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Resolved ({tickets.filter(t => t.status === 'resolved').length})
|
|
194
|
-
</button>
|
|
124
|
+
<button onClick={handleCreate}>Create Ticket</button>
|
|
125
|
+
{tickets?.map(ticket => (
|
|
126
|
+
<div key={ticket.uuid}>
|
|
127
|
+
<h3>{ticket.subject}</h3>
|
|
128
|
+
<span>Status: {ticket.status}</span>
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
195
131
|
</div>
|
|
196
132
|
);
|
|
197
133
|
}
|
|
@@ -199,38 +135,69 @@ function TicketFilters() {
|
|
|
199
135
|
|
|
200
136
|
## API Reference
|
|
201
137
|
|
|
202
|
-
###
|
|
138
|
+
### SupportContext
|
|
203
139
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
140
|
+
```typescript
|
|
141
|
+
interface SupportContextValue {
|
|
142
|
+
// Tickets
|
|
143
|
+
tickets: Ticket[] | undefined;
|
|
144
|
+
isLoadingTickets: boolean;
|
|
145
|
+
ticketsError: Error | undefined;
|
|
146
|
+
refreshTickets: () => Promise<void>;
|
|
147
|
+
|
|
148
|
+
// Ticket operations
|
|
149
|
+
getTicket: (uuid: string) => Promise<Ticket | undefined>;
|
|
150
|
+
createTicket: (data: TicketRequest) => Promise<Ticket>;
|
|
151
|
+
updateTicket: (uuid: string, data: TicketRequest) => Promise<Ticket>;
|
|
152
|
+
partialUpdateTicket: (uuid: string, data: PatchedTicketRequest) => Promise<Ticket>;
|
|
153
|
+
deleteTicket: (uuid: string) => Promise<void>;
|
|
154
|
+
|
|
155
|
+
// Messages
|
|
156
|
+
getMessages: (ticketUuid: string) => Promise<Message[] | undefined>;
|
|
157
|
+
createMessage: (ticketUuid: string, data: MessageCreateRequest) => Promise<Message>;
|
|
158
|
+
updateMessage: (ticketUuid: string, messageUuid: string, data: MessageRequest) => Promise<Message>;
|
|
159
|
+
deleteMessage: (ticketUuid: string, messageUuid: string) => Promise<void>;
|
|
160
|
+
refreshMessages: (ticketUuid: string) => Promise<void>;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
216
163
|
|
|
217
|
-
|
|
164
|
+
### Ticket Type
|
|
218
165
|
|
|
219
166
|
```typescript
|
|
220
167
|
interface Ticket {
|
|
221
|
-
|
|
168
|
+
uuid: string;
|
|
222
169
|
subject: string;
|
|
223
|
-
description: string;
|
|
224
170
|
status: 'open' | 'in_progress' | 'resolved' | 'closed';
|
|
225
|
-
priority: 'low' | 'medium' | 'high' | 'urgent';
|
|
226
|
-
category: string;
|
|
227
|
-
assigned_to?: string;
|
|
228
171
|
created_at: string;
|
|
229
172
|
updated_at: string;
|
|
230
|
-
comments?: Comment[];
|
|
231
173
|
}
|
|
232
174
|
```
|
|
233
175
|
|
|
176
|
+
### TicketRequest Type
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
interface TicketRequest {
|
|
180
|
+
subject: string;
|
|
181
|
+
message: string;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Exports
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Main layout (includes all UI)
|
|
189
|
+
import { SupportLayout } from '@djangocfg/ext-support';
|
|
190
|
+
|
|
191
|
+
// Hooks and context
|
|
192
|
+
import {
|
|
193
|
+
SupportProvider,
|
|
194
|
+
useSupportContext
|
|
195
|
+
} from '@djangocfg/ext-support/hooks';
|
|
196
|
+
|
|
197
|
+
// Server-safe config
|
|
198
|
+
import { extensionConfig } from '@djangocfg/ext-support/config';
|
|
199
|
+
```
|
|
200
|
+
|
|
234
201
|
## License
|
|
235
202
|
|
|
236
203
|
MIT
|
package/dist/config.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_ext_base = require("@djangocfg/ext-base");
|
|
|
27
27
|
// package.json
|
|
28
28
|
var package_default = {
|
|
29
29
|
name: "@djangocfg/ext-support",
|
|
30
|
-
version: "1.0.
|
|
30
|
+
version: "1.0.17",
|
|
31
31
|
description: "Support ticket system extension for DjangoCFG",
|
|
32
32
|
keywords: [
|
|
33
33
|
"django",
|
|
@@ -95,7 +95,7 @@ var package_default = {
|
|
|
95
95
|
next: "^16",
|
|
96
96
|
"p-retry": "^7.0.0",
|
|
97
97
|
react: "^19",
|
|
98
|
-
"react-hook-form": "7.
|
|
98
|
+
"react-hook-form": "^7.69.0",
|
|
99
99
|
swr: "^2.3.7",
|
|
100
100
|
zod: "^4.1.13"
|
|
101
101
|
},
|
package/dist/config.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createExtensionConfig } from "@djangocfg/ext-base";
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "@djangocfg/ext-support",
|
|
7
|
-
version: "1.0.
|
|
7
|
+
version: "1.0.17",
|
|
8
8
|
description: "Support ticket system extension for DjangoCFG",
|
|
9
9
|
keywords: [
|
|
10
10
|
"django",
|
|
@@ -72,7 +72,7 @@ var package_default = {
|
|
|
72
72
|
next: "^16",
|
|
73
73
|
"p-retry": "^7.0.0",
|
|
74
74
|
react: "^19",
|
|
75
|
-
"react-hook-form": "7.
|
|
75
|
+
"react-hook-form": "^7.69.0",
|
|
76
76
|
swr: "^2.3.7",
|
|
77
77
|
zod: "^4.1.13"
|
|
78
78
|
},
|
package/dist/hooks.cjs
CHANGED
|
@@ -2656,7 +2656,7 @@ var SupportLayout = () => {
|
|
|
2656
2656
|
// package.json
|
|
2657
2657
|
var package_default = {
|
|
2658
2658
|
name: "@djangocfg/ext-support",
|
|
2659
|
-
version: "1.0.
|
|
2659
|
+
version: "1.0.17",
|
|
2660
2660
|
description: "Support ticket system extension for DjangoCFG",
|
|
2661
2661
|
keywords: [
|
|
2662
2662
|
"django",
|
|
@@ -2724,7 +2724,7 @@ var package_default = {
|
|
|
2724
2724
|
next: "^16",
|
|
2725
2725
|
"p-retry": "^7.0.0",
|
|
2726
2726
|
react: "^19",
|
|
2727
|
-
"react-hook-form": "7.
|
|
2727
|
+
"react-hook-form": "^7.69.0",
|
|
2728
2728
|
swr: "^2.3.7",
|
|
2729
2729
|
zod: "^4.1.13"
|
|
2730
2730
|
},
|
package/dist/hooks.js
CHANGED
|
@@ -2646,7 +2646,7 @@ var SupportLayout = () => {
|
|
|
2646
2646
|
// package.json
|
|
2647
2647
|
var package_default = {
|
|
2648
2648
|
name: "@djangocfg/ext-support",
|
|
2649
|
-
version: "1.0.
|
|
2649
|
+
version: "1.0.17",
|
|
2650
2650
|
description: "Support ticket system extension for DjangoCFG",
|
|
2651
2651
|
keywords: [
|
|
2652
2652
|
"django",
|
|
@@ -2714,7 +2714,7 @@ var package_default = {
|
|
|
2714
2714
|
next: "^16",
|
|
2715
2715
|
"p-retry": "^7.0.0",
|
|
2716
2716
|
react: "^19",
|
|
2717
|
-
"react-hook-form": "7.
|
|
2717
|
+
"react-hook-form": "^7.69.0",
|
|
2718
2718
|
swr: "^2.3.7",
|
|
2719
2719
|
zod: "^4.1.13"
|
|
2720
2720
|
},
|
package/dist/index.cjs
CHANGED
|
@@ -2656,7 +2656,7 @@ var SupportLayout = () => {
|
|
|
2656
2656
|
// package.json
|
|
2657
2657
|
var package_default = {
|
|
2658
2658
|
name: "@djangocfg/ext-support",
|
|
2659
|
-
version: "1.0.
|
|
2659
|
+
version: "1.0.17",
|
|
2660
2660
|
description: "Support ticket system extension for DjangoCFG",
|
|
2661
2661
|
keywords: [
|
|
2662
2662
|
"django",
|
|
@@ -2724,7 +2724,7 @@ var package_default = {
|
|
|
2724
2724
|
next: "^16",
|
|
2725
2725
|
"p-retry": "^7.0.0",
|
|
2726
2726
|
react: "^19",
|
|
2727
|
-
"react-hook-form": "7.
|
|
2727
|
+
"react-hook-form": "^7.69.0",
|
|
2728
2728
|
swr: "^2.3.7",
|
|
2729
2729
|
zod: "^4.1.13"
|
|
2730
2730
|
},
|
package/dist/index.js
CHANGED
|
@@ -2646,7 +2646,7 @@ var SupportLayout = () => {
|
|
|
2646
2646
|
// package.json
|
|
2647
2647
|
var package_default = {
|
|
2648
2648
|
name: "@djangocfg/ext-support",
|
|
2649
|
-
version: "1.0.
|
|
2649
|
+
version: "1.0.17",
|
|
2650
2650
|
description: "Support ticket system extension for DjangoCFG",
|
|
2651
2651
|
keywords: [
|
|
2652
2652
|
"django",
|
|
@@ -2714,7 +2714,7 @@ var package_default = {
|
|
|
2714
2714
|
next: "^16",
|
|
2715
2715
|
"p-retry": "^7.0.0",
|
|
2716
2716
|
react: "^19",
|
|
2717
|
-
"react-hook-form": "7.
|
|
2717
|
+
"react-hook-form": "^7.69.0",
|
|
2718
2718
|
swr: "^2.3.7",
|
|
2719
2719
|
zod: "^4.1.13"
|
|
2720
2720
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ext-support",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "Support ticket system extension for DjangoCFG",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"django",
|
|
@@ -59,24 +59,24 @@
|
|
|
59
59
|
"check": "tsc --noEmit"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"@djangocfg/api": "^2.1.
|
|
63
|
-
"@djangocfg/ext-base": "^1.0.
|
|
64
|
-
"@djangocfg/ui-core": "^2.1.
|
|
62
|
+
"@djangocfg/api": "^2.1.108",
|
|
63
|
+
"@djangocfg/ext-base": "^1.0.12",
|
|
64
|
+
"@djangocfg/ui-core": "^2.1.108",
|
|
65
65
|
"consola": "^3.4.2",
|
|
66
66
|
"lucide-react": "^0.545.0",
|
|
67
67
|
"moment": "^2.30.1",
|
|
68
68
|
"next": "^16",
|
|
69
69
|
"p-retry": "^7.0.0",
|
|
70
70
|
"react": "^19",
|
|
71
|
-
"react-hook-form": "7.
|
|
71
|
+
"react-hook-form": "^7.69.0",
|
|
72
72
|
"swr": "^2.3.7",
|
|
73
73
|
"zod": "^4.1.13"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@djangocfg/api": "^2.1.
|
|
77
|
-
"@djangocfg/ext-base": "^1.0.
|
|
78
|
-
"@djangocfg/ui-core": "^2.1.
|
|
79
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
76
|
+
"@djangocfg/api": "^2.1.108",
|
|
77
|
+
"@djangocfg/ext-base": "^1.0.12",
|
|
78
|
+
"@djangocfg/ui-core": "^2.1.108",
|
|
79
|
+
"@djangocfg/typescript-config": "^2.1.108",
|
|
80
80
|
"@types/node": "^24.7.2",
|
|
81
81
|
"@types/react": "^19.0.0",
|
|
82
82
|
"consola": "^3.4.2",
|