@djangocfg/ext-support 1.0.6 → 1.0.8
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/dist/config.cjs +4 -1
- package/dist/config.js +4 -1
- package/dist/hooks.cjs +79 -89
- package/dist/hooks.js +78 -89
- package/dist/index.cjs +79 -89
- package/dist/index.d.cts +0 -97
- package/dist/index.d.ts +0 -97
- package/dist/index.js +78 -89
- package/package.json +10 -7
- package/src/api/generated/ext_support/CLAUDE.md +80 -0
- package/src/api/generated/ext_support/_utils/fetchers/ext_support__support.ts +1 -8
- package/src/api/generated/ext_support/_utils/fetchers/index.ts +1 -8
- package/src/api/generated/ext_support/_utils/hooks/ext_support__support.ts +1 -8
- package/src/api/generated/ext_support/_utils/hooks/index.ts +1 -8
- package/src/api/generated/ext_support/_utils/schemas/index.ts +1 -8
- package/src/api/generated/ext_support/api-instance.ts +1 -8
- package/src/api/generated/ext_support/enums.ts +1 -8
- package/src/api/generated/ext_support/errors.ts +1 -8
- package/src/api/generated/ext_support/ext_support__support/index.ts +1 -8
- package/src/api/generated/ext_support/ext_support__support/models.ts +1 -8
- package/src/api/generated/ext_support/http.ts +1 -8
- package/src/api/generated/ext_support/index.ts +1 -8
- package/src/api/generated/ext_support/logger.ts +1 -8
- package/src/api/generated/ext_support/retry.ts +1 -8
- package/src/api/generated/ext_support/storage.ts +1 -8
- package/src/api/generated/ext_support/validation-events.ts +1 -8
- package/src/api/index.ts +2 -1
- package/src/config.ts +1 -0
- package/src/contexts/SupportContext.tsx +9 -13
- package/src/contexts/SupportExtensionProvider.tsx +1 -0
- package/src/layouts/SupportLayout/SupportLayout.tsx +5 -13
- package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +8 -18
- package/src/layouts/SupportLayout/components/MessageInput.tsx +5 -10
- package/src/layouts/SupportLayout/components/MessageList.tsx +25 -22
- package/src/layouts/SupportLayout/components/TicketCard.tsx +10 -10
- package/src/layouts/SupportLayout/components/TicketList.tsx +6 -4
- package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +9 -2
- package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +2 -0
- package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -2,13 +2,15 @@ import { createConsola, consola } from 'consola';
|
|
|
2
2
|
import pRetry, { AbortError } from 'p-retry';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { createExtensionAPI } from '@djangocfg/ext-base/api';
|
|
5
|
+
import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
|
|
5
6
|
import React7, { createContext, useState, useCallback, useEffect, useContext, useRef } from 'react';
|
|
7
|
+
import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, Badge } from '@djangocfg/ui-nextjs';
|
|
6
8
|
import useSWR, { useSWRConfig } from 'swr';
|
|
7
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
+
import moment2 from 'moment';
|
|
11
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
8
12
|
import { useAuth } from '@djangocfg/api/auth';
|
|
9
13
|
import useSWRInfinite from 'swr/infinite';
|
|
10
|
-
import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, cn, Badge } from '@djangocfg/ui-nextjs';
|
|
11
|
-
import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
|
|
12
14
|
import { useForm } from 'react-hook-form';
|
|
13
15
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
14
16
|
import { createExtensionConfig } from '@djangocfg/ext-base';
|
|
@@ -1775,6 +1777,67 @@ function useSupportContext() {
|
|
|
1775
1777
|
}
|
|
1776
1778
|
return context;
|
|
1777
1779
|
}
|
|
1780
|
+
var getStatusBadgeVariant = (status) => {
|
|
1781
|
+
switch (status) {
|
|
1782
|
+
case "open":
|
|
1783
|
+
return "default";
|
|
1784
|
+
case "waiting_for_user":
|
|
1785
|
+
return "secondary";
|
|
1786
|
+
case "waiting_for_admin":
|
|
1787
|
+
return "outline";
|
|
1788
|
+
case "resolved":
|
|
1789
|
+
return "outline";
|
|
1790
|
+
case "closed":
|
|
1791
|
+
return "secondary";
|
|
1792
|
+
default:
|
|
1793
|
+
return "default";
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
var formatRelativeTime = (date) => {
|
|
1797
|
+
if (!date) return "N/A";
|
|
1798
|
+
const m = moment2.utc(date).local();
|
|
1799
|
+
const now = moment2();
|
|
1800
|
+
const diffInSeconds = now.diff(m, "seconds");
|
|
1801
|
+
if (diffInSeconds < 60) return "Just now";
|
|
1802
|
+
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
|
1803
|
+
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
|
1804
|
+
if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
1805
|
+
return m.format("MMM D, YYYY");
|
|
1806
|
+
};
|
|
1807
|
+
var TicketCard = ({ ticket, isSelected, onClick }) => {
|
|
1808
|
+
return /* @__PURE__ */ jsx(
|
|
1809
|
+
Card,
|
|
1810
|
+
{
|
|
1811
|
+
className: cn(
|
|
1812
|
+
"cursor-pointer transition-all duration-200 ease-out",
|
|
1813
|
+
"hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
|
|
1814
|
+
"active:scale-[0.98]",
|
|
1815
|
+
isSelected && "bg-accent border-primary shadow-sm"
|
|
1816
|
+
),
|
|
1817
|
+
onClick,
|
|
1818
|
+
children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
|
|
1819
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
|
|
1820
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
|
|
1821
|
+
(ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
|
|
1822
|
+
Badge,
|
|
1823
|
+
{
|
|
1824
|
+
variant: "destructive",
|
|
1825
|
+
className: "ml-2 shrink-0 animate-pulse",
|
|
1826
|
+
children: ticket.unanswered_messages_count
|
|
1827
|
+
}
|
|
1828
|
+
)
|
|
1829
|
+
] }),
|
|
1830
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1831
|
+
/* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
|
|
1832
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
1833
|
+
/* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
|
|
1834
|
+
/* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
|
|
1835
|
+
] })
|
|
1836
|
+
] }) })
|
|
1837
|
+
] })
|
|
1838
|
+
}
|
|
1839
|
+
);
|
|
1840
|
+
};
|
|
1778
1841
|
|
|
1779
1842
|
// src/layouts/SupportLayout/events.ts
|
|
1780
1843
|
var SUPPORT_LAYOUT_EVENTS = {
|
|
@@ -2039,71 +2102,6 @@ function useSupportLayoutContext() {
|
|
|
2039
2102
|
}
|
|
2040
2103
|
return context;
|
|
2041
2104
|
}
|
|
2042
|
-
var getStatusBadgeVariant = (status) => {
|
|
2043
|
-
switch (status) {
|
|
2044
|
-
case "open":
|
|
2045
|
-
return "default";
|
|
2046
|
-
case "waiting_for_user":
|
|
2047
|
-
return "secondary";
|
|
2048
|
-
case "waiting_for_admin":
|
|
2049
|
-
return "outline";
|
|
2050
|
-
case "resolved":
|
|
2051
|
-
return "outline";
|
|
2052
|
-
case "closed":
|
|
2053
|
-
return "secondary";
|
|
2054
|
-
default:
|
|
2055
|
-
return "default";
|
|
2056
|
-
}
|
|
2057
|
-
};
|
|
2058
|
-
var formatRelativeTime = (date) => {
|
|
2059
|
-
if (!date) return "N/A";
|
|
2060
|
-
const now = /* @__PURE__ */ new Date();
|
|
2061
|
-
const messageDate = new Date(date);
|
|
2062
|
-
const diffInSeconds = Math.floor((now.getTime() - messageDate.getTime()) / 1e3);
|
|
2063
|
-
if (diffInSeconds < 60) return "Just now";
|
|
2064
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
|
2065
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
|
2066
|
-
if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
2067
|
-
return new Date(date).toLocaleDateString("en-US", {
|
|
2068
|
-
year: "numeric",
|
|
2069
|
-
month: "short",
|
|
2070
|
-
day: "numeric"
|
|
2071
|
-
});
|
|
2072
|
-
};
|
|
2073
|
-
var TicketCard = ({ ticket, isSelected, onClick }) => {
|
|
2074
|
-
return /* @__PURE__ */ jsx(
|
|
2075
|
-
Card,
|
|
2076
|
-
{
|
|
2077
|
-
className: cn(
|
|
2078
|
-
"cursor-pointer transition-all duration-200 ease-out",
|
|
2079
|
-
"hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
|
|
2080
|
-
"active:scale-[0.98]",
|
|
2081
|
-
isSelected && "bg-accent border-primary shadow-sm"
|
|
2082
|
-
),
|
|
2083
|
-
onClick,
|
|
2084
|
-
children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
|
|
2085
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
|
|
2086
|
-
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
|
|
2087
|
-
(ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
|
|
2088
|
-
Badge,
|
|
2089
|
-
{
|
|
2090
|
-
variant: "destructive",
|
|
2091
|
-
className: "ml-2 shrink-0 animate-pulse",
|
|
2092
|
-
children: ticket.unanswered_messages_count
|
|
2093
|
-
}
|
|
2094
|
-
)
|
|
2095
|
-
] }),
|
|
2096
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2097
|
-
/* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
|
|
2098
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2099
|
-
/* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
|
|
2100
|
-
/* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
|
|
2101
|
-
] })
|
|
2102
|
-
] }) })
|
|
2103
|
-
] })
|
|
2104
|
-
}
|
|
2105
|
-
);
|
|
2106
|
-
};
|
|
2107
2105
|
var TicketList = () => {
|
|
2108
2106
|
const { selectedTicket, selectTicket } = useSupportLayoutContext();
|
|
2109
2107
|
const {
|
|
@@ -2209,28 +2207,23 @@ var TicketList = () => {
|
|
|
2209
2207
|
};
|
|
2210
2208
|
var formatTime = (date) => {
|
|
2211
2209
|
if (!date) return "";
|
|
2212
|
-
return
|
|
2213
|
-
hour: "2-digit",
|
|
2214
|
-
minute: "2-digit"
|
|
2215
|
-
});
|
|
2210
|
+
return moment2.utc(date).local().format("hh:mm A");
|
|
2216
2211
|
};
|
|
2217
2212
|
var formatDate = (date) => {
|
|
2218
2213
|
if (!date) return "";
|
|
2219
|
-
return
|
|
2220
|
-
year: "numeric",
|
|
2221
|
-
month: "short",
|
|
2222
|
-
day: "numeric"
|
|
2223
|
-
});
|
|
2214
|
+
return moment2.utc(date).local().format("MMM D, YYYY");
|
|
2224
2215
|
};
|
|
2225
2216
|
var MessageBubble = ({ message, isFromUser, currentUser }) => {
|
|
2226
2217
|
const sender = message.sender;
|
|
2218
|
+
const senderInitial = sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S";
|
|
2219
|
+
const userInitial = currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || null;
|
|
2227
2220
|
return /* @__PURE__ */ jsxs(
|
|
2228
2221
|
"div",
|
|
2229
2222
|
{
|
|
2230
2223
|
className: `flex gap-3 ${isFromUser ? "justify-end" : "justify-start"}
|
|
2231
2224
|
animate-in fade-in slide-in-from-bottom-2 duration-300`,
|
|
2232
2225
|
children: [
|
|
2233
|
-
!isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) :
|
|
2226
|
+
!isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
|
|
2234
2227
|
/* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-1 flex-1 max-w-[80%] ${isFromUser ? "items-end" : "items-start"}`, children: [
|
|
2235
2228
|
!isFromUser && sender && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-1", children: [
|
|
2236
2229
|
sender.display_username || sender.email || "Support Team",
|
|
@@ -2245,7 +2238,7 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
|
|
|
2245
2238
|
),
|
|
2246
2239
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground px-1", children: formatTime(message.created_at) })
|
|
2247
2240
|
] }),
|
|
2248
|
-
isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children:
|
|
2241
|
+
isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children: userInitial || /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) }) })
|
|
2249
2242
|
]
|
|
2250
2243
|
}
|
|
2251
2244
|
);
|
|
@@ -2363,7 +2356,7 @@ var MessageList = () => {
|
|
|
2363
2356
|
messages.map((message, index) => {
|
|
2364
2357
|
const isFromUser = message.sender?.id && user?.id && String(message.sender.id) === String(user.id) || message.sender?.email && user?.email && message.sender.email === user.email || message.is_from_author && selectedTicket?.user && user?.id && String(selectedTicket.user) === String(user.id);
|
|
2365
2358
|
const previousMessage = index > 0 ? messages[index - 1] : null;
|
|
2366
|
-
const showDateSeparator = previousMessage &&
|
|
2359
|
+
const showDateSeparator = previousMessage && moment2.utc(previousMessage.created_at || "").format("YYYY-MM-DD") !== moment2.utc(message.created_at || "").format("YYYY-MM-DD");
|
|
2367
2360
|
return /* @__PURE__ */ jsxs(React7.Fragment, { children: [
|
|
2368
2361
|
showDateSeparator && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 my-4", children: [
|
|
2369
2362
|
/* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
|
|
@@ -2400,17 +2393,10 @@ var MessageInput = () => {
|
|
|
2400
2393
|
try {
|
|
2401
2394
|
await sendMessage(message.trim());
|
|
2402
2395
|
setMessage("");
|
|
2403
|
-
toast(
|
|
2404
|
-
title: "Success",
|
|
2405
|
-
description: "Message sent successfully"
|
|
2406
|
-
});
|
|
2396
|
+
toast.success("Message sent successfully");
|
|
2407
2397
|
} catch (error) {
|
|
2408
2398
|
supportLogger.error("Failed to send message:", error);
|
|
2409
|
-
toast(
|
|
2410
|
-
title: "Error",
|
|
2411
|
-
description: "Failed to send message",
|
|
2412
|
-
variant: "destructive"
|
|
2413
|
-
});
|
|
2399
|
+
toast.error("Failed to send message");
|
|
2414
2400
|
} finally {
|
|
2415
2401
|
setIsSending(false);
|
|
2416
2402
|
}
|
|
@@ -2631,7 +2617,7 @@ var SupportLayout = () => {
|
|
|
2631
2617
|
// package.json
|
|
2632
2618
|
var package_default = {
|
|
2633
2619
|
name: "@djangocfg/ext-support",
|
|
2634
|
-
version: "1.0.
|
|
2620
|
+
version: "1.0.8",
|
|
2635
2621
|
description: "Support ticket system extension for DjangoCFG",
|
|
2636
2622
|
keywords: [
|
|
2637
2623
|
"django",
|
|
@@ -2692,9 +2678,11 @@ var package_default = {
|
|
|
2692
2678
|
peerDependencies: {
|
|
2693
2679
|
"@djangocfg/api": "workspace:*",
|
|
2694
2680
|
"@djangocfg/ext-base": "workspace:*",
|
|
2681
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
2695
2682
|
"@djangocfg/ui-nextjs": "workspace:*",
|
|
2696
2683
|
consola: "^3.4.2",
|
|
2697
2684
|
"lucide-react": "^0.545.0",
|
|
2685
|
+
moment: "^2.30.1",
|
|
2698
2686
|
next: "^15.5.7",
|
|
2699
2687
|
"p-retry": "^7.0.0",
|
|
2700
2688
|
react: "^18 || ^19",
|
|
@@ -2709,6 +2697,7 @@ var package_default = {
|
|
|
2709
2697
|
"@types/node": "^24.7.2",
|
|
2710
2698
|
"@types/react": "^19.0.0",
|
|
2711
2699
|
consola: "^3.4.2",
|
|
2700
|
+
moment: "^2.30.1",
|
|
2712
2701
|
"p-retry": "^7.0.0",
|
|
2713
2702
|
swr: "^2.3.7",
|
|
2714
2703
|
tsup: "^8.5.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ext-support",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Support ticket system extension for DjangoCFG",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"django",
|
|
@@ -59,11 +59,13 @@
|
|
|
59
59
|
"check": "tsc --noEmit"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"@djangocfg/api": "^2.1.
|
|
63
|
-
"@djangocfg/ext-base": "^1.0.
|
|
64
|
-
"@djangocfg/ui-
|
|
62
|
+
"@djangocfg/api": "^2.1.91",
|
|
63
|
+
"@djangocfg/ext-base": "^1.0.8",
|
|
64
|
+
"@djangocfg/ui-core": "^2.1.91",
|
|
65
|
+
"@djangocfg/ui-nextjs": "^2.1.91",
|
|
65
66
|
"consola": "^3.4.2",
|
|
66
67
|
"lucide-react": "^0.545.0",
|
|
68
|
+
"moment": "^2.30.1",
|
|
67
69
|
"next": "^15.5.7",
|
|
68
70
|
"p-retry": "^7.0.0",
|
|
69
71
|
"react": "^18 || ^19",
|
|
@@ -72,12 +74,13 @@
|
|
|
72
74
|
"zod": "^4.1.13"
|
|
73
75
|
},
|
|
74
76
|
"devDependencies": {
|
|
75
|
-
"@djangocfg/api": "^2.1.
|
|
76
|
-
"@djangocfg/ext-base": "^1.0.
|
|
77
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
77
|
+
"@djangocfg/api": "^2.1.91",
|
|
78
|
+
"@djangocfg/ext-base": "^1.0.8",
|
|
79
|
+
"@djangocfg/typescript-config": "^2.1.91",
|
|
78
80
|
"@types/node": "^24.7.2",
|
|
79
81
|
"@types/react": "^19.0.0",
|
|
80
82
|
"consola": "^3.4.2",
|
|
83
|
+
"moment": "^2.30.1",
|
|
81
84
|
"p-retry": "^7.0.0",
|
|
82
85
|
"swr": "^2.3.7",
|
|
83
86
|
"tsup": "^8.5.0",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Django CFG API - Typescript Client
|
|
2
|
+
|
|
3
|
+
Auto-generated. **Do not edit manually.**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
python manage.py generate_client --groups ext_support --typescript
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Stats
|
|
10
|
+
|
|
11
|
+
| | |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Version | 3.0.3 |
|
|
14
|
+
| Operations | 12 |
|
|
15
|
+
| Schemas | 11 |
|
|
16
|
+
|
|
17
|
+
## Resources
|
|
18
|
+
|
|
19
|
+
- **support** (12 ops)
|
|
20
|
+
|
|
21
|
+
## Operations
|
|
22
|
+
|
|
23
|
+
**support:**
|
|
24
|
+
- `POST` /cfg/support/tickets/ → `cfg_support_tickets_create`
|
|
25
|
+
- `DELETE` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_destroy`
|
|
26
|
+
- `GET` /cfg/support/tickets/ → `cfg_support_tickets_list`
|
|
27
|
+
- `POST` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_create`
|
|
28
|
+
- `DELETE` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_destroy`
|
|
29
|
+
- `GET` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_list`
|
|
30
|
+
- `PATCH` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_partial_update`
|
|
31
|
+
- `GET` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_retrieve`
|
|
32
|
+
- `PUT` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_update`
|
|
33
|
+
- `PATCH` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_partial_update`
|
|
34
|
+
- `GET` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_retrieve`
|
|
35
|
+
- `PUT` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_update`
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { APIClient } from './';
|
|
41
|
+
|
|
42
|
+
const client = new APIClient({ baseUrl, token });
|
|
43
|
+
|
|
44
|
+
await client.support.list();
|
|
45
|
+
await client.support.retrieve({ id: 1 });
|
|
46
|
+
await client.support.create({ ... });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**SWR Hooks:**
|
|
50
|
+
```typescript
|
|
51
|
+
import { useSupportList } from './hooks';
|
|
52
|
+
const { data, isLoading } = useSupportList();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## How It Works
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
DRF ViewSets → drf-spectacular → OpenAPI → IR Parser → Generator → This Client
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Configuration** (`api/config.py`):
|
|
62
|
+
```python
|
|
63
|
+
openapi_client = OpenAPIClientConfig(
|
|
64
|
+
enabled=True,
|
|
65
|
+
groups=[OpenAPIGroupConfig(name="ext_support", apps=["..."])],
|
|
66
|
+
generate_zod_schemas=True, # → schemas.ts
|
|
67
|
+
generate_fetchers=True, # → fetchers.ts
|
|
68
|
+
generate_swr_hooks=True, # → hooks.ts
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Copy to Next.js** (if `nextjs_admin` configured):
|
|
73
|
+
```python
|
|
74
|
+
nextjs_admin = NextJsAdminConfig(
|
|
75
|
+
project_path="../frontend/apps/...",
|
|
76
|
+
api_output_path="app/_lib/api/generated",
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
@see https://djangocfg.com/docs/features/api-generation
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Typed fetchers for Support
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Typed Fetchers - Universal API functions
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
'use client';
|
|
10
3
|
|
|
11
4
|
/**
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
'use client';
|
|
10
3
|
|
|
11
4
|
/**
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Zod Schemas - Runtime validation and type inference
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Global API Instance - Singleton configuration
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* * `open` - Open
|
|
11
4
|
* * `waiting_for_user` - Waiting for User
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* API Error Classes
|
|
11
4
|
*
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
export * from "./client";
|
|
10
3
|
export * as Models from "./models";
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
import * as Enums from "../enums";
|
|
10
3
|
|
|
11
4
|
/**
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* HTTP Client Adapter Pattern
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Django CFG API - API Client with JWT Management
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* API Logger with Consola
|
|
11
4
|
* Beautiful console logging for API requests and responses
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Retry Configuration and Utilities
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Storage adapters for cross-platform token storage.
|
|
11
4
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3
|
-
*
|
|
4
|
-
* This file is automatically generated by DjangoCFG.
|
|
5
|
-
* Any manual changes will be lost when the code is regenerated.
|
|
6
|
-
*
|
|
7
|
-
* @see https://djangocfg.com/docs/features/modules/django-client/overview/
|
|
8
|
-
*/
|
|
1
|
+
// Auto-generated by DjangoCFG - see CLAUDE.md
|
|
9
2
|
/**
|
|
10
3
|
* Zod Validation Events - Browser CustomEvent integration
|
|
11
4
|
*
|
package/src/api/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { createExtensionAPI } from '@djangocfg/ext-base/api';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Support Extension API
|
|
3
5
|
*
|
|
4
6
|
* Pre-configured API instance with shared authentication
|
|
5
7
|
*/
|
|
6
8
|
import { API } from './generated/ext_support';
|
|
7
|
-
import { createExtensionAPI } from '@djangocfg/ext-base/api';
|
|
8
9
|
|
|
9
10
|
export const apiSupport = createExtensionAPI(API);
|
package/src/config.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, { createContext,
|
|
3
|
+
import React, { createContext, ReactNode, useContext } from 'react';
|
|
4
|
+
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
useSupportTicketsMessagesList,
|
|
12
|
-
useSupportTicketsMessagesRetrieve,
|
|
13
|
-
useCreateSupportTicketsMessagesCreate,
|
|
14
|
-
useUpdateSupportTicketsMessagesUpdate,
|
|
15
|
-
usePartialUpdateSupportTicketsMessagesPartialUpdate,
|
|
16
|
-
useDeleteSupportTicketsMessagesDestroy,
|
|
6
|
+
useCreateSupportTicketsCreate, useCreateSupportTicketsMessagesCreate,
|
|
7
|
+
useDeleteSupportTicketsDestroy, useDeleteSupportTicketsMessagesDestroy,
|
|
8
|
+
usePartialUpdateSupportTicketsMessagesPartialUpdate,
|
|
9
|
+
usePartialUpdateSupportTicketsPartialUpdate, useSupportTicketsList,
|
|
10
|
+
useSupportTicketsMessagesList, useSupportTicketsMessagesRetrieve, useSupportTicketsRetrieve,
|
|
11
|
+
useUpdateSupportTicketsMessagesUpdate, useUpdateSupportTicketsUpdate
|
|
17
12
|
} from '../api/generated/ext_support/_utils/hooks';
|
|
13
|
+
|
|
18
14
|
import type {
|
|
19
15
|
Ticket,
|
|
20
16
|
TicketRequest,
|