@clubmed/usg-chat-ui 1.0.1 → 1.2.5
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/chunks/_commonjsHelpers.js +9 -0
- package/chunks/_commonjsHelpers.js.map +1 -0
- package/chunks/browser.js +579 -0
- package/chunks/browser.js.map +1 -0
- package/chunks/client.js +27323 -0
- package/chunks/client.js.map +1 -0
- package/chunks/index.js +59 -32
- package/chunks/index.js.map +1 -1
- package/chunks/index2.js +32 -59
- package/chunks/index2.js.map +1 -1
- package/chunks/index3.js +22 -740
- package/chunks/index3.js.map +1 -1
- package/chunks/index4.js +740 -22
- package/chunks/index4.js.map +1 -1
- package/chunks/index5.js +1 -1
- package/chunks/index6.js +144 -150
- package/chunks/index6.js.map +1 -1
- package/chunks/index7.js +14 -13
- package/chunks/index7.js.map +1 -1
- package/chunks/magic-string.es.js +664 -0
- package/chunks/magic-string.es.js.map +1 -0
- package/chunks/react.esm.js +10007 -0
- package/chunks/react.esm.js.map +1 -0
- package/chunks/{collaboration.js → useCollaboration.js} +536 -523
- package/chunks/useCollaboration.js.map +1 -0
- package/chunks/vi.2VT5v0um.js +10573 -0
- package/chunks/vi.2VT5v0um.js.map +1 -0
- package/contexts/ChatContext.d.ts +2 -1
- package/contexts/ChatContext.js +32 -30
- package/contexts/ChatContext.js.map +1 -1
- package/core/interfaces/ChatConfig.d.ts +4 -0
- package/core/interfaces/StoryVersion.d.ts +7 -2
- package/index.d.ts +1 -0
- package/molecules/AiElements/Message.js +1 -1
- package/molecules/AiElements/Response.js +15 -13
- package/molecules/AiElements/Response.js.map +1 -1
- package/molecules/AiElements/Sources.d.ts +2 -2
- package/molecules/AiElements/Sources.js.map +1 -1
- package/molecules/Buttons/Button.d.ts +1 -1
- package/molecules/Buttons/Button.js +2 -2
- package/molecules/{AiElements → CodeBlock}/CodeBlock.d.ts +5 -2
- package/molecules/CodeBlock/CodeBlock.js +128 -0
- package/molecules/CodeBlock/CodeBlock.js.map +1 -0
- package/molecules/CodeBlock/CodeBlock.test.d.ts +1 -0
- package/molecules/CodeBlock/CodeBlock.test.js +3158 -0
- package/molecules/CodeBlock/CodeBlock.test.js.map +1 -0
- package/molecules/CodeBlock/highlightCode.d.ts +2 -0
- package/molecules/CodeBlock/highlightCode.js +5850 -0
- package/molecules/CodeBlock/highlightCode.js.map +1 -0
- package/molecules/CodeBlock/highlightCode.test.d.ts +1 -0
- package/molecules/CodeBlock/highlightCode.test.js +47 -0
- package/molecules/CodeBlock/highlightCode.test.js.map +1 -0
- package/molecules/Collapsibles/Collapsible.js +1 -1
- package/molecules/Forms/InputGroups/InputGroup.js +1 -1
- package/molecules/Labels/Label.js +2 -2
- package/molecules/Notifications/{Sonner.js → Toaster.js} +2 -2
- package/molecules/Notifications/Toaster.js.map +1 -0
- package/molecules/Notifications/{use-toast.js → useToast.js} +1 -1
- package/molecules/Notifications/useToast.js.map +1 -0
- package/{organisms → molecules}/RichText/DynamicEditor.js.map +1 -1
- package/molecules/RichText/EditorWithAI.js +55854 -0
- package/molecules/RichText/EditorWithAI.js.map +1 -0
- package/molecules/RichText/useCollaboration.d.ts +9 -0
- package/molecules/RichText/useCollaboration.js +8 -0
- package/molecules/RichText/useCollaboration.js.map +1 -0
- package/molecules/RichText/useCollaboration.test.d.ts +1 -0
- package/molecules/RichText/useCollaboration.test.js +70 -0
- package/molecules/RichText/useCollaboration.test.js.map +1 -0
- package/molecules/Tabs/Tabs.js +1 -1
- package/organisms/canvas/ApiDocsCanvas.js +15 -15
- package/organisms/canvas/ApiDocsCanvas.js.map +1 -1
- package/organisms/canvas/ReleaseNoteCanvas.js +2 -2
- package/organisms/canvas/ReleaseNoteCanvas.js.map +1 -1
- package/organisms/canvas/StoryCanvas.js +2 -2
- package/organisms/canvas/StoryCanvas.js.map +1 -1
- package/organisms/chat/MessageActions.js +1 -1
- package/organisms/chat/MessageActions.js.map +1 -1
- package/organisms/chat/hooks/useChat.js +1 -1
- package/organisms/chat/hooks/useChat.js.map +1 -1
- package/organisms/chat/hooks/useChatKeyboardsShortcuts.js +16 -33
- package/organisms/chat/hooks/useChatKeyboardsShortcuts.js.map +1 -1
- package/organisms/chat/hooks/useConversations.js +1 -1
- package/organisms/chat/hooks/useConversations.js.map +1 -1
- package/organisms/settings/SettingsModal.js +1 -1
- package/package.json +3 -4
- package/.npm/_logs/2026-01-19T16_54_30_380Z-debug-0.log +0 -19
- package/.npm/_logs/2026-01-19T16_54_30_467Z-debug-0.log +0 -19
- package/.npm/_logs/2026-01-19T16_54_30_553Z-debug-0.log +0 -14
- package/chunks/collaboration.js.map +0 -1
- package/core/collaboration.d.ts +0 -6
- package/core/collaboration.js +0 -5
- package/core/collaboration.js.map +0 -1
- package/molecules/AiElements/CodeBlock.js +0 -6525
- package/molecules/AiElements/CodeBlock.js.map +0 -1
- package/molecules/Notifications/Sonner.js.map +0 -1
- package/molecules/Notifications/use-toast.js.map +0 -1
- package/molecules/index.d.ts +0 -28
- package/molecules/index.js +0 -88
- package/molecules/index.js.map +0 -1
- package/organisms/RichText/EditorWithAI.js +0 -83167
- package/organisms/RichText/EditorWithAI.js.map +0 -1
- /package/molecules/Notifications/{Sonner.d.ts → Toaster.d.ts} +0 -0
- /package/molecules/Notifications/{use-toast.d.ts → useToast.d.ts} +0 -0
- /package/{organisms → molecules}/RichText/DynamicEditor.d.ts +0 -0
- /package/{organisms → molecules}/RichText/DynamicEditor.js +0 -0
- /package/{organisms → molecules}/RichText/EditorWithAI.d.ts +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Y from "yjs";
|
|
2
|
+
export declare function __resetCollaborationProvidersForTests(): void;
|
|
3
|
+
export declare function useCollaboration({ documentId, collaborationEnabled }: {
|
|
4
|
+
documentId?: string;
|
|
5
|
+
collaborationEnabled?: boolean;
|
|
6
|
+
}): {
|
|
7
|
+
doc: Y.Doc | null;
|
|
8
|
+
provider: import('@y-sweet/client').YSweetProvider | null;
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCollaboration.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { r as s } from "../../chunks/react.esm.js";
|
|
2
|
+
import { _ as u, D as b, c as v, u as d } from "../../chunks/useCollaboration.js";
|
|
3
|
+
import { useChatConfig as p } from "../../contexts/ChatContext.js";
|
|
4
|
+
import { v as r, d as h, b as f, a as C, i, g as t } from "../../chunks/vi.2VT5v0um.js";
|
|
5
|
+
r.mock("@clubmed/usg-chat-ui/contexts/ChatContext", () => ({
|
|
6
|
+
useChatConfig: r.fn()
|
|
7
|
+
}));
|
|
8
|
+
r.mock("@y-sweet/client", () => ({
|
|
9
|
+
createYjsProvider: r.fn()
|
|
10
|
+
}));
|
|
11
|
+
const k = r.mocked(p), c = r.mocked(v), B = () => {
|
|
12
|
+
const n = {};
|
|
13
|
+
return {
|
|
14
|
+
on: r.fn((o, e) => {
|
|
15
|
+
n[o] = n[o] ?? [], n[o].push(e);
|
|
16
|
+
}),
|
|
17
|
+
emit: (o, e) => {
|
|
18
|
+
var a;
|
|
19
|
+
(a = n[o]) == null || a.forEach((l) => l(e));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
h("useCollaboration", () => {
|
|
24
|
+
let n;
|
|
25
|
+
f(() => {
|
|
26
|
+
u(), n = r.spyOn(console, "log").mockImplementation(() => {
|
|
27
|
+
}), k.mockReturnValue({
|
|
28
|
+
apiUrl: "https://api.local",
|
|
29
|
+
collaborationUrl: "https://collab.local",
|
|
30
|
+
isAuthenticated: !0,
|
|
31
|
+
setDbUserId: r.fn()
|
|
32
|
+
}), c.mockImplementation(
|
|
33
|
+
() => B()
|
|
34
|
+
);
|
|
35
|
+
}), C(() => {
|
|
36
|
+
n.mockRestore(), r.clearAllMocks(), u();
|
|
37
|
+
}), i("returns null doc/provider when collaboration disabled or missing documentId", () => {
|
|
38
|
+
const o = s(
|
|
39
|
+
() => d({ documentId: "doc-1", collaborationEnabled: !1 })
|
|
40
|
+
);
|
|
41
|
+
t(o.result.current).toEqual({ doc: null, provider: null });
|
|
42
|
+
const e = s(
|
|
43
|
+
() => d({ documentId: void 0, collaborationEnabled: !0 })
|
|
44
|
+
);
|
|
45
|
+
t(e.result.current.doc).toBeNull(), t(e.result.current.provider).toBeNull(), t(c).not.toHaveBeenCalled();
|
|
46
|
+
}), i("creates one provider per document and reuses cached entries", () => {
|
|
47
|
+
const { result: o, rerender: e } = s(
|
|
48
|
+
(m) => d(m),
|
|
49
|
+
{
|
|
50
|
+
initialProps: { documentId: "doc-1", collaborationEnabled: !0 }
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
t(c).toHaveBeenCalledTimes(1), t(c).toHaveBeenCalledWith(
|
|
54
|
+
t.any(b),
|
|
55
|
+
"doc-1",
|
|
56
|
+
"https://collab.local"
|
|
57
|
+
);
|
|
58
|
+
const a = o.current.doc, l = o.current.provider;
|
|
59
|
+
e({ documentId: "doc-1", collaborationEnabled: !0 }), t(o.current.doc).toBe(a), t(o.current.provider).toBe(l), t(c).toHaveBeenCalledTimes(1), e({ documentId: "doc-2", collaborationEnabled: !0 }), t(c).toHaveBeenCalledTimes(2), t(o.current.provider).not.toBe(l);
|
|
60
|
+
}), i("wires status and sync events for logging", () => {
|
|
61
|
+
const { result: o } = s(
|
|
62
|
+
() => d({ documentId: "doc-events", collaborationEnabled: !0 })
|
|
63
|
+
), e = o.current.provider;
|
|
64
|
+
t(e).not.toBeNull(), e == null || e.emit("status", { status: "connected" }), e == null || e.emit("sync", !0), t(n).toHaveBeenCalledWith(
|
|
65
|
+
"[doc-events] Y-Sweet status:",
|
|
66
|
+
"connected"
|
|
67
|
+
), t(n).toHaveBeenCalledWith("[doc-events] Synced:", !0);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=useCollaboration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCollaboration.test.js","sources":["../../../lib/molecules/RichText/useCollaboration.test.tsx"],"sourcesContent":["import {renderHook} from \"@testing-library/react\";\nimport {afterEach, beforeEach, describe, expect, it, vi} from \"vitest\";\nimport {useCollaboration, __resetCollaborationProvidersForTests} from \"./useCollaboration\";\nimport {useChatConfig} from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport {createYjsProvider} from \"@y-sweet/client\";\nimport * as Y from \"yjs\";\n\nvi.mock(\"@clubmed/usg-chat-ui/contexts/ChatContext\", () => ({\n useChatConfig: vi.fn(),\n}));\n\nvi.mock(\"@y-sweet/client\", () => ({\n createYjsProvider: vi.fn(),\n}));\n\nconst useChatConfigMock = vi.mocked(useChatConfig);\nconst createYjsProviderMock = vi.mocked(createYjsProvider);\n\ntype MockProvider = {\n on: ReturnType<typeof vi.fn>;\n emit: (event: string, payload: unknown) => void;\n};\n\nconst createMockProvider = (): MockProvider => {\n const handlers: Record<string, Array<(payload: unknown) => void>> = {};\n return {\n on: vi.fn((event: string, handler: (payload: unknown) => void) => {\n handlers[event] = handlers[event] ?? [];\n handlers[event]!.push(handler);\n }),\n emit: (event: string, payload: unknown) => {\n handlers[event]?.forEach((handler) => handler(payload));\n },\n };\n};\n\ndescribe(\"useCollaboration\", () => {\n let consoleSpy: ReturnType<typeof vi.spyOn>;\n\n beforeEach(() => {\n __resetCollaborationProvidersForTests();\n consoleSpy = vi.spyOn(console, \"log\").mockImplementation(() => {});\n useChatConfigMock.mockReturnValue({\n apiUrl: \"https://api.local\",\n collaborationUrl: \"https://collab.local\",\n isAuthenticated: true,\n setDbUserId: vi.fn(),\n });\n createYjsProviderMock.mockImplementation(\n () =>\n createMockProvider() as unknown as ReturnType<typeof createYjsProvider>\n );\n });\n\n afterEach(() => {\n consoleSpy.mockRestore();\n vi.clearAllMocks();\n __resetCollaborationProvidersForTests();\n });\n\n it(\"returns null doc/provider when collaboration disabled or missing documentId\", () => {\n const disabled = renderHook(() =>\n useCollaboration({documentId: \"doc-1\", collaborationEnabled: false})\n );\n expect(disabled.result.current).toEqual({doc: null, provider: null});\n\n const missingId = renderHook(() =>\n useCollaboration({documentId: undefined, collaborationEnabled: true})\n );\n expect(missingId.result.current.doc).toBeNull();\n expect(missingId.result.current.provider).toBeNull();\n expect(createYjsProviderMock).not.toHaveBeenCalled();\n });\n\n it(\"creates one provider per document and reuses cached entries\", () => {\n const {result, rerender} = renderHook(\n (props: {documentId?: string; collaborationEnabled?: boolean}) =>\n useCollaboration(props),\n {\n initialProps: {documentId: \"doc-1\", collaborationEnabled: true},\n }\n );\n\n expect(createYjsProviderMock).toHaveBeenCalledTimes(1);\n expect(createYjsProviderMock).toHaveBeenCalledWith(\n expect.any(Y.Doc),\n \"doc-1\",\n \"https://collab.local\"\n );\n\n const firstDoc = result.current.doc;\n const firstProvider = result.current.provider;\n\n rerender({documentId: \"doc-1\", collaborationEnabled: true});\n expect(result.current.doc).toBe(firstDoc);\n expect(result.current.provider).toBe(firstProvider);\n expect(createYjsProviderMock).toHaveBeenCalledTimes(1);\n\n rerender({documentId: \"doc-2\", collaborationEnabled: true});\n expect(createYjsProviderMock).toHaveBeenCalledTimes(2);\n expect(result.current.provider).not.toBe(firstProvider);\n });\n\n it(\"wires status and sync events for logging\", () => {\n const {result} = renderHook(() =>\n useCollaboration({documentId: \"doc-events\", collaborationEnabled: true})\n );\n\n const provider = result.current.provider as MockProvider | null;\n expect(provider).not.toBeNull();\n provider?.emit(\"status\", {status: \"connected\"});\n provider?.emit(\"sync\", true);\n\n expect(consoleSpy).toHaveBeenCalledWith(\n \"[doc-events] Y-Sweet status:\",\n \"connected\"\n );\n expect(consoleSpy).toHaveBeenCalledWith(\"[doc-events] Synced:\", true);\n });\n});\n"],"names":["vi","useChatConfigMock","useChatConfig","createYjsProviderMock","createYjsProvider","createMockProvider","handlers","event","handler","payload","_a","describe","consoleSpy","beforeEach","__resetCollaborationProvidersForTests","afterEach","it","disabled","renderHook","useCollaboration","expect","missingId","result","rerender","props","Y.Doc","firstDoc","firstProvider","provider"],"mappings":"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"}
|
package/molecules/Tabs/Tabs.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as i } from "react/jsx-runtime";
|
|
|
3
3
|
import * as a from "react";
|
|
4
4
|
import w from "react";
|
|
5
5
|
import { c as L, f as $, e as U, P as A, a as S, d as B, b as pe } from "../../chunks/index5.js";
|
|
6
|
-
import { u as O } from "../../chunks/
|
|
6
|
+
import { u as O } from "../../chunks/index3.js";
|
|
7
7
|
import { cn as K } from "../../utils/cn.js";
|
|
8
8
|
function ve(e) {
|
|
9
9
|
const t = e + "CollectionProvider", [n, o] = L(t), [d, f] = n(
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as e, jsxs as r } from "react/jsx-runtime";
|
|
3
3
|
import { useCanvasStore as d } from "../../utils/canvas-store.js";
|
|
4
|
-
import { Card as
|
|
5
|
-
import { Response as
|
|
6
|
-
import { Sources as
|
|
4
|
+
import { Card as n, CardContent as s } from "../../molecules/Cards/Card.js";
|
|
5
|
+
import { Response as h } from "../../molecules/AiElements/Response.js";
|
|
6
|
+
import { Sources as m, SourcesTrigger as u, SourcesContent as p, Source as f } from "../../molecules/AiElements/Sources.js";
|
|
7
7
|
import { c as g } from "../../chunks/createLucideIcon.js";
|
|
8
8
|
/**
|
|
9
9
|
* @license lucide-react v0.545.0 - ISC
|
|
@@ -20,37 +20,37 @@ const x = [
|
|
|
20
20
|
key: "ruj8y"
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
|
-
],
|
|
23
|
+
], c = g("book-open", x);
|
|
24
24
|
function A() {
|
|
25
25
|
const { apiDocsData: a } = d();
|
|
26
26
|
if (!a)
|
|
27
27
|
return /* @__PURE__ */ e("div", { className: "flex items-center justify-center h-full p-6", children: /* @__PURE__ */ e("p", { className: "text-muted-foreground", children: "No API documentation available" }) });
|
|
28
|
-
const { answer: l, sources:
|
|
28
|
+
const { answer: l, sources: t } = a;
|
|
29
29
|
return /* @__PURE__ */ r("div", { className: "p-6 space-y-6", children: [
|
|
30
30
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-3", children: [
|
|
31
|
-
/* @__PURE__ */ e("div", { className: "flex h-12 w-12 items-center justify-center rounded-xl bg-foreground text-primary-foreground shadow-lg", children: /* @__PURE__ */ e(
|
|
31
|
+
/* @__PURE__ */ e("div", { className: "flex h-12 w-12 items-center justify-center rounded-xl bg-foreground text-primary-foreground shadow-lg", children: /* @__PURE__ */ e(c, { className: "h-6 w-6" }) }),
|
|
32
32
|
/* @__PURE__ */ r("div", { children: [
|
|
33
33
|
/* @__PURE__ */ e("h1", { className: "text-2xl font-bold text-foreground", children: "API Documentation" }),
|
|
34
34
|
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "ClubMed API Reference" })
|
|
35
35
|
] })
|
|
36
36
|
] }),
|
|
37
|
-
/* @__PURE__ */ e(
|
|
38
|
-
|
|
39
|
-
/* @__PURE__ */ e(u, { count:
|
|
40
|
-
/* @__PURE__ */ e(p, { children:
|
|
41
|
-
(
|
|
37
|
+
/* @__PURE__ */ e(n, { children: /* @__PURE__ */ e(s, { children: /* @__PURE__ */ e(h, { children: l }) }) }),
|
|
38
|
+
t && t.length > 0 && /* @__PURE__ */ e(n, { children: /* @__PURE__ */ e(s, { className: "pt-4", children: /* @__PURE__ */ r(m, { children: [
|
|
39
|
+
/* @__PURE__ */ e(u, { count: t.length }),
|
|
40
|
+
/* @__PURE__ */ e(p, { children: t.map(
|
|
41
|
+
(o, i) => /* @__PURE__ */ e(
|
|
42
42
|
f,
|
|
43
43
|
{
|
|
44
|
-
href:
|
|
45
|
-
title:
|
|
44
|
+
href: o.href || "#",
|
|
45
|
+
title: o.title
|
|
46
46
|
},
|
|
47
47
|
i
|
|
48
48
|
)
|
|
49
49
|
) })
|
|
50
50
|
] }) }) }),
|
|
51
|
-
/* @__PURE__ */ e(
|
|
51
|
+
/* @__PURE__ */ e(n, { className: "bg-muted border border-border", children: /* @__PURE__ */ r(s, { children: [
|
|
52
52
|
/* @__PURE__ */ r("h3", { className: "font-semibold text-foreground mb-3 flex items-center gap-2", children: [
|
|
53
|
-
/* @__PURE__ */ e(
|
|
53
|
+
/* @__PURE__ */ e(c, { className: "h-5 w-5" }),
|
|
54
54
|
"Quick Tips"
|
|
55
55
|
] }),
|
|
56
56
|
/* @__PURE__ */ r("ul", { className: "space-y-2 text-sm text-muted-foreground", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiDocsCanvas.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/book-open.js","../../../lib/organisms/canvas/ApiDocsCanvas.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 7v14\", key: \"1akyts\" }],\n [\n \"path\",\n {\n d: \"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\",\n key: \"ruj8y\"\n }\n ]\n];\nconst BookOpen = createLucideIcon(\"book-open\", __iconNode);\n\nexport { __iconNode, BookOpen as default };\n//# sourceMappingURL=book-open.js.map\n","\"use client\";\n\nimport { useCanvasStore, type ApiDocsCanvasData } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { Card, CardContent } from \"@clubmed/usg-chat-ui/molecules/Cards/Card\";\nimport { BookOpen } from \"lucide-react\";\nimport { Response } from \"@clubmed/usg-chat-ui/molecules/AiElements/Response\";\nimport {\n Source,\n Sources,\n SourcesContent,\n SourcesTrigger,\n} from \"@clubmed/usg-chat-ui/molecules/AiElements/Sources\";\n\nexport function ApiDocsCanvas() {\n const { apiDocsData } = useCanvasStore();\n\n if (!apiDocsData) {\n return (\n <div className=\"flex items-center justify-center h-full p-6\">\n <p className=\"text-muted-foreground\">No API documentation available</p>\n </div>\n );\n }\n\n const { answer, sources } = apiDocsData;\n\n return (\n <div className=\"p-6 space-y-6\">\n {/* Documentation Header */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-xl bg-foreground text-primary-foreground shadow-lg\">\n <BookOpen className=\"h-6 w-6\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n API Documentation\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n ClubMed API Reference\n </p>\n </div>\n </div>\n\n {/* Main Answer */}\n <Card>\n <CardContent
|
|
1
|
+
{"version":3,"file":"ApiDocsCanvas.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/book-open.js","../../../lib/organisms/canvas/ApiDocsCanvas.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 7v14\", key: \"1akyts\" }],\n [\n \"path\",\n {\n d: \"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\",\n key: \"ruj8y\"\n }\n ]\n];\nconst BookOpen = createLucideIcon(\"book-open\", __iconNode);\n\nexport { __iconNode, BookOpen as default };\n//# sourceMappingURL=book-open.js.map\n","\"use client\";\n\nimport { useCanvasStore, type ApiDocsCanvasData } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { Card, CardContent } from \"@clubmed/usg-chat-ui/molecules/Cards/Card\";\nimport { BookOpen } from \"lucide-react\";\nimport { Response } from \"@clubmed/usg-chat-ui/molecules/AiElements/Response\";\nimport {\n Source,\n Sources,\n SourcesContent,\n SourcesTrigger,\n} from \"@clubmed/usg-chat-ui/molecules/AiElements/Sources\";\n\nexport function ApiDocsCanvas() {\n const { apiDocsData } = useCanvasStore();\n\n if (!apiDocsData) {\n return (\n <div className=\"flex items-center justify-center h-full p-6\">\n <p className=\"text-muted-foreground\">No API documentation available</p>\n </div>\n );\n }\n\n const { answer, sources } = apiDocsData;\n\n return (\n <div className=\"p-6 space-y-6\">\n {/* Documentation Header */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-xl bg-foreground text-primary-foreground shadow-lg\">\n <BookOpen className=\"h-6 w-6\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n API Documentation\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n ClubMed API Reference\n </p>\n </div>\n </div>\n\n {/* Main Answer */}\n <Card>\n <CardContent>\n <Response>{answer}</Response>\n </CardContent>\n </Card>\n\n {/* Sources using AI Elements */}\n {sources && sources.length > 0 && (\n <Card>\n <CardContent className=\"pt-4\">\n <Sources>\n <SourcesTrigger count={sources.length} />\n <SourcesContent>\n {sources.map(\n (\n source: ApiDocsCanvasData[\"sources\"][number],\n index: number\n ) => (\n <Source\n key={index}\n href={source.href || \"#\"}\n title={source.title}\n />\n ))}\n </SourcesContent>\n </Sources>\n </CardContent>\n </Card>\n )}\n\n {/* API Tips */}\n <Card className=\"bg-muted border border-border\">\n <CardContent>\n <h3 className=\"font-semibold text-foreground mb-3 flex items-center gap-2\">\n <BookOpen className=\"h-5 w-5\" />\n Quick Tips\n </h3>\n <ul className=\"space-y-2 text-sm text-muted-foreground\">\n <li className=\"flex gap-2\">\n <span className=\"text-foreground\">•</span>\n <span>\n All API requests require authentication using your API token\n </span>\n </li>\n <li className=\"flex gap-2\">\n <span className=\"text-foreground\">•</span>\n <span>\n Use the base URL from your project settings for all endpoints\n </span>\n </li>\n <li className=\"flex gap-2\">\n <span className=\"text-foreground\">•</span>\n <span>\n Check the HTTP status codes for error handling\n </span>\n </li>\n </ul>\n </CardContent>\n </Card>\n </div>\n );\n}\n\n"],"names":["__iconNode","BookOpen","createLucideIcon","ApiDocsCanvas","apiDocsData","useCanvasStore","jsx","answer","sources","jsxs","Card","CardContent","Response","Sources","SourcesTrigger","SourcesContent","source","index","Source"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { jsx as r, jsxs as a, Fragment as l } from "react/jsx-runtime";
|
|
3
3
|
import { useState as c, useEffect as f, useMemo as u } from "react";
|
|
4
4
|
import { useCanvasStore as h } from "../../utils/canvas-store.js";
|
|
5
|
-
import { DynamicEditor as v } from "
|
|
6
|
-
import { useToast as C } from "../../molecules/Notifications/
|
|
5
|
+
import { DynamicEditor as v } from "../../molecules/RichText/DynamicEditor.js";
|
|
6
|
+
import { useToast as C } from "../../molecules/Notifications/useToast.js";
|
|
7
7
|
import { Button as b } from "../../molecules/Buttons/Button.js";
|
|
8
8
|
import { C as x } from "../../chunks/check.js";
|
|
9
9
|
import { C as N } from "../../chunks/copy.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReleaseNoteCanvas.js","sources":["../../../lib/organisms/canvas/ReleaseNoteCanvas.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState, useEffect } from \"react\";\nimport { useCanvasStore } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { DynamicEditor } from \"@clubmed/usg-chat-ui/
|
|
1
|
+
{"version":3,"file":"ReleaseNoteCanvas.js","sources":["../../../lib/organisms/canvas/ReleaseNoteCanvas.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState, useEffect } from \"react\";\nimport { useCanvasStore } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { DynamicEditor } from \"@clubmed/usg-chat-ui/molecules/RichText/DynamicEditor\";\nimport { useToast } from \"@clubmed/usg-chat-ui/molecules/Notifications/useToast\";\nimport { Button } from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport { Copy, Check } from \"lucide-react\";\n\nexport function ReleaseNoteCanvas() {\n const { releaseNoteData } = useCanvasStore();\n const [editorMarkdown, setEditorMarkdown] = useState<string>(\"\");\n const [copied, setCopied] = useState(false);\n const { toast } = useToast();\n\n // Initialize editorMarkdown state with initial content\n useEffect(() => {\n if (!editorMarkdown && releaseNoteData && releaseNoteData.release_note) {\n setEditorMarkdown(releaseNoteData.release_note);\n }\n }, [releaseNoteData, editorMarkdown]);\n\n const handleCopy = async () => {\n try {\n const contentToCopy = editorMarkdown || releaseNoteData && releaseNoteData.release_note;\n if (contentToCopy) {\n await navigator.clipboard.writeText(contentToCopy);\n setCopied(true);\n toast({\n title: \"Copié !\",\n description: \"La release note a été copiée dans le presse-papier.\",\n });\n setTimeout(() => setCopied(false), 2000);\n }\n } catch {\n toast({\n title: \"Erreur\",\n description: \"Impossible de copier le contenu.\",\n variant: \"destructive\",\n });\n }\n };\n\n // Build simple AI context (optional, but good for consistency if we enable AI editing)\n const aiContext = useMemo(() => {\n return {\n release_note: releaseNoteData?.release_note || \"\",\n };\n }, [releaseNoteData]);\n\n if (!releaseNoteData) {\n return (\n <div className=\"flex items-center justify-center h-full p-6\">\n <p className=\"text-muted-foreground\">No release note data available</p>\n </div>\n );\n }\n\n\n\n return (\n <div className=\"h-full flex flex-col overflow-hidden\">\n {/* Header avec bouton de copie */}\n <div className=\"flex items-center justify-end px-8 pt-6 pb-4 border-b border-border\">\n <div className=\"flex items-center gap-3\">\n <Button\n onClick={handleCopy}\n className=\"gap-2\"\n variant=\"secondary\"\n >\n {copied ? (\n <>\n <Check className=\"h-4 w-4\" />\n Copié\n </>\n ) : (\n <>\n <Copy className=\"h-4 w-4\" />\n Copier\n </>\n )}\n </Button>\n </div>\n </div>\n\n {/* Editor */}\n <div className=\"flex-1 overflow-y-auto scroll-smooth\">\n <div className=\"px-8 pt-6 pb-16\">\n <div className=\"border border-border rounded-lg overflow-hidden shadow-sm\">\n <DynamicEditor\n initialMarkdown={releaseNoteData.release_note}\n editable={true}\n aiEnabled={false} // Disable AI for now as we don't have specific tools for release note editing yet\n aiContext={aiContext as Record<string, unknown>}\n onChange={(markdown: string) => {\n setEditorMarkdown(markdown);\n }}\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n\n\n\n\n\n\n\n\n\n\n"],"names":["ReleaseNoteCanvas","releaseNoteData","useCanvasStore","editorMarkdown","setEditorMarkdown","useState","copied","setCopied","toast","useToast","useEffect","handleCopy","contentToCopy","aiContext","useMemo","jsxs","jsx","Button","Fragment","Check","Copy","DynamicEditor","markdown"],"mappings":";;;;;;;;;AASO,SAASA,IAAoB;AAClC,QAAM,EAAE,iBAAAC,EAAA,IAAoBC,EAAA,GACtB,CAACC,GAAgBC,CAAiB,IAAIC,EAAiB,EAAE,GACzD,CAACC,GAAQC,CAAS,IAAIF,EAAS,EAAK,GACpC,EAAE,OAAAG,EAAA,IAAUC,EAAA;AAGlB,EAAAC,EAAU,MAAM;AACd,IAAI,CAACP,KAAkBF,KAAmBA,EAAgB,gBACxDG,EAAkBH,EAAgB,YAAY;AAAA,EAElD,GAAG,CAACA,GAAiBE,CAAc,CAAC;AAEpC,QAAMQ,IAAa,YAAY;AAC7B,QAAI;AACF,YAAMC,IAAgBT,KAAkBF,KAAmBA,EAAgB;AAC3E,MAAIW,MACF,MAAM,UAAU,UAAU,UAAUA,CAAa,GACjDL,EAAU,EAAI,GACdC,EAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa;AAAA,MAAA,CACd,GACD,WAAW,MAAMD,EAAU,EAAK,GAAG,GAAI;AAAA,IAE3C,QAAQ;AACN,MAAAC,EAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAAA,EACF,GAGMK,IAAYC,EAAQ,OACjB;AAAA,IACL,eAAcb,KAAA,gBAAAA,EAAiB,iBAAgB;AAAA,EAAA,IAEhD,CAACA,CAAe,CAAC;AAEpB,SAAKA,IAWH,gBAAAc,EAAC,OAAA,EAAI,WAAU,wCAEb,UAAA;AAAA,IAAA,gBAAAC,EAAC,SAAI,WAAU,uEACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA,gBAAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,SAASN;AAAA,QACT,WAAU;AAAA,QACV,SAAQ;AAAA,QAEP,cACC,gBAAAI,EAAAG,GAAA,EACE,UAAA;AAAA,UAAA,gBAAAF,EAACG,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,EAAA,CAE/B,IAEA,gBAAAJ,EAAAG,GAAA,EACE,UAAA;AAAA,UAAA,gBAAAF,EAACI,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,EAAA,CAE9B;AAAA,MAAA;AAAA,IAAA,GAGN,EAAA,CACF;AAAA,IAGA,gBAAAJ,EAAC,OAAA,EAAI,WAAU,wCACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA,gBAAAA;AAAA,MAACK;AAAA,MAAA;AAAA,QACC,iBAAiBpB,EAAgB;AAAA,QACjC,UAAU;AAAA,QACV,WAAW;AAAA,QACX,WAAAY;AAAA,QACA,UAAU,CAACS,MAAqB;AAC9B,UAAAlB,EAAkBkB,CAAQ;AAAA,QAC5B;AAAA,MAAA;AAAA,IAAA,EACF,CACF,GACF,EAAA,CACF;AAAA,EAAA,GACF,IAjDE,gBAAAN,EAAC,SAAI,WAAU,+CACb,4BAAC,KAAA,EAAE,WAAU,yBAAwB,UAAA,iCAAA,CAA8B,EAAA,CACrE;AAiDN;"}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { jsx as i, jsxs as d, Fragment as v } from "react/jsx-runtime";
|
|
3
3
|
import { useState as f, useMemo as g, useEffect as E } from "react";
|
|
4
4
|
import { useCanvasStore as _ } from "../../utils/canvas-store.js";
|
|
5
|
-
import { DynamicEditor as P } from "
|
|
5
|
+
import { DynamicEditor as P } from "../../molecules/RichText/DynamicEditor.js";
|
|
6
6
|
import { useChatConfig as $, useChatApiClient as L } from "../../contexts/ChatContext.js";
|
|
7
|
-
import { useToast as T } from "../../molecules/Notifications/
|
|
7
|
+
import { useToast as T } from "../../molecules/Notifications/useToast.js";
|
|
8
8
|
import { Button as I } from "../../molecules/Buttons/Button.js";
|
|
9
9
|
import { L as z } from "../../chunks/loader-circle.js";
|
|
10
10
|
import { S as F } from "../../chunks/send.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoryCanvas.js","sources":["../../../lib/organisms/canvas/StoryCanvas.tsx"],"sourcesContent":["\"use client\";\n\nimport {useEffect, useMemo, useState} from \"react\";\nimport {type StoryCanvasData, useCanvasStore} from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport {DynamicEditor} from \"@clubmed/usg-chat-ui/organisms/RichText/DynamicEditor\";\nimport type {DocAIContext} from \"@clubmed/usg-chat-ui/core/interfaces\";\nimport {useChatApiClient, useChatConfig} from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport {useToast} from \"@clubmed/usg-chat-ui/molecules/Notifications/use-toast\";\nimport {Button} from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport {Loader2, Send} from \"lucide-react\";\n\ninterface StoryBodyProps {\n storyData: StoryCanvasData;\n}\n\nfunction StoryBody({\n storyData,\n }: StoryBodyProps) {\n const {story} = storyData;\n const {projectKey} = useCanvasStore();\n const [isPublishing, setIsPublishing] = useState(false);\n const [publishedIssue, setPublishedIssue] = useState<{ key: string; url: string } | null>(null);\n const [editorMarkdown, setEditorMarkdown] = useState<string>(\"\");\n const {toast} = useToast();\n const {dbUserId} = useChatConfig();\n const apiClient = useChatApiClient();\n\n // Build AI context for the editor (must be before conditional return)\n const aiContext: DocAIContext = useMemo(() => {\n if (!storyData) {\n return {\n brief: undefined,\n projectKey: projectKey || undefined,\n story: {\n title: \"\",\n description: \"\",\n acceptance_criteria: [],\n story_points: null,\n priority: \"Medium\",\n labels: [],\n technical_considerations: null,\n },\n validation: undefined,\n };\n }\n\n const {story, validation, structured_brief} = storyData;\n\n // Extract brief from structured_brief if available\n const brief = structured_brief\n ? Object.entries(structured_brief)\n .map(([key, value]) => `${key.replace(/_/g, \" \")}: ${String(value)}`)\n .join(\"\\n\")\n : undefined;\n\n // Handle technical_considerations\n let technicalConsiderations: string | object | null = null;\n if (story.technical_considerations) {\n if (typeof story.technical_considerations === 'string') {\n technicalConsiderations = story.technical_considerations;\n } else {\n technicalConsiderations = JSON.stringify(story.technical_considerations);\n }\n }\n\n return {\n brief,\n projectKey: projectKey || undefined,\n story: {\n title: story.title,\n description: story.description,\n acceptance_criteria: story.acceptance_criteria || [],\n technical_considerations: technicalConsiderations,\n story_points: null, // story_points might not be in canvas data\n priority: story.priority || \"Medium\",\n labels: story.labels || [],\n },\n validation: validation ? {\n is_valid: validation.is_valid,\n completeness_score: validation.completeness_score,\n coherence_score: validation.coherence_score,\n style_alignment_score: validation.style_alignment_score,\n issues: validation.issues,\n suggestions: validation.suggestions,\n } : undefined,\n };\n }, [storyData, projectKey]);\n\n // Initialize editor markdown with initial content\n const initialMarkdown = useMemo(() => {\n const storyTitle = story.title || \"Story\";\n\n // If description already contains full markdown (starts with #), check if title is included\n if (story.description && story.description.trim().startsWith('#')) {\n // Check if the first heading matches the story title (case-insensitive, ignoring special chars)\n const firstLine = story.description.trim().split('\\n')[0];\n const normalizedTitle = storyTitle.toLowerCase().replace(/[^\\w\\s]/g, '').trim();\n const normalizedFirstHeading = firstLine.replace(/^#+\\s*/, '').toLowerCase().replace(/[^\\w\\s]/g, '').trim();\n\n // If title is already present in the description, return as-is\n if (normalizedFirstHeading === normalizedTitle || normalizedFirstHeading.includes(normalizedTitle) || normalizedTitle.includes(normalizedFirstHeading)) {\n return story.description;\n }\n\n // Otherwise, prepend the story title\n return `# ${storyTitle}\\n\\n${story.description}`;\n }\n\n // Otherwise, build markdown from structured fields (backward compatibility)\n let markdown = `# ${storyTitle}\\n\\n`;\n\n // Description (already in Markdown format from the LLM)\n if (story.description) {\n markdown += `${story.description}\\n\\n`;\n }\n\n return markdown;\n }, [story]);\n\n // Initialize editorMarkdown state with initial content\n useEffect(() => {\n if (!editorMarkdown && initialMarkdown) {\n setEditorMarkdown(initialMarkdown);\n }\n }, [editorMarkdown, initialMarkdown]); // Only run when initialMarkdown changes\n\n // Extract title from markdown (first heading)\n const extractTitleFromMarkdown = (markdown: string): string => {\n if (!markdown) return story.title || \"Story\";\n\n // Find the first heading (starts with #)\n const lines = markdown.trim().split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('#')) {\n // Extract text after # symbols\n const title = trimmed.replace(/^#+\\s*/, '').trim();\n if (title) {\n return title;\n }\n }\n }\n\n // Fallback to original title if no heading found\n return story.title || \"Story\";\n };\n\n const handlePublish = async () => {\n if (!projectKey) {\n toast({\n title: \"Erreur\",\n description: \"Aucun projet sélectionné. Veuillez configurer un projet dans les paramètres.\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsPublishing(true);\n try {\n // Extract title from editor content if available, otherwise use initial markdown\n const currentMarkdown = editorMarkdown || initialMarkdown;\n const updatedTitle = extractTitleFromMarkdown(currentMarkdown);\n\n // Create updated story object with the modified title and description\n const updatedStory = {\n ...story,\n title: updatedTitle,\n description: currentMarkdown, // Use the current editor content as description\n };\n\n const response = await apiClient.publishStory(updatedStory, projectKey, dbUserId || undefined);\n setPublishedIssue(response.jira_issue);\n toast({\n title: \"Succès\",\n description: `User story publiée avec succès : ${response.jira_issue.key}`,\n });\n } catch (error) {\n toast({\n title: \"Erreur\",\n description: error instanceof Error ? error.message : \"Échec de la publication de la user story\",\n variant: \"destructive\",\n });\n } finally {\n setIsPublishing(false);\n }\n };\n\n return (\n <div className=\"h-full flex flex-col overflow-hidden\">\n {/* Header avec bouton de publication */}\n <div className=\"flex items-center justify-end px-8 pt-6 pb-4 border-b border-border\">\n <div className=\"flex items-center gap-3\">\n {publishedIssue && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span>Publiée:</span>\n <a\n href={publishedIssue.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline font-medium\"\n >\n {publishedIssue.key}\n </a>\n </div>\n )}\n <Button\n onClick={handlePublish}\n disabled={isPublishing || !projectKey || !!publishedIssue}\n className=\"gap-2\"\n >\n {isPublishing ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\"/>\n Publication...\n </>\n ) : (\n <>\n <Send className=\"h-4 w-4\"/>\n Publier sur Jira\n </>\n )}\n </Button>\n </div>\n </div>\n\n {/* Editor */}\n <div className=\"flex-1 overflow-y-auto scroll-smooth\">\n <div className=\"px-8 pt-6 pb-16\">\n <div className=\"border border-border rounded-lg overflow-hidden shadow-sm\">\n <DynamicEditor\n initialMarkdown={initialMarkdown}\n editable={true}\n aiEnabled={true}\n aiContext={aiContext as Record<string, unknown>}\n onChange={(markdown: string) => {\n setEditorMarkdown(markdown);\n }}\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport function StoryCanvas() {\n const {storyData} = useCanvasStore();\n\n if (!storyData) {\n return (\n <div className=\"flex items-center justify-center h-full p-6\">\n <p className=\"text-muted-foreground\">No story data available</p>\n </div>\n );\n }\n\n return (\n <StoryBody storyData={storyData}/>\n );\n}\n"],"names":["StoryBody","storyData","story","projectKey","useCanvasStore","isPublishing","setIsPublishing","useState","publishedIssue","setPublishedIssue","editorMarkdown","setEditorMarkdown","toast","useToast","dbUserId","useChatConfig","apiClient","useChatApiClient","aiContext","useMemo","validation","structured_brief","brief","key","value","technicalConsiderations","initialMarkdown","storyTitle","firstLine","normalizedTitle","normalizedFirstHeading","markdown","useEffect","extractTitleFromMarkdown","lines","line","trimmed","title","handlePublish","currentMarkdown","updatedTitle","updatedStory","response","error","jsxs","jsx","Button","Fragment","Loader2","Send","DynamicEditor","StoryCanvas"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StoryCanvas.js","sources":["../../../lib/organisms/canvas/StoryCanvas.tsx"],"sourcesContent":["\"use client\";\n\nimport {useEffect, useMemo, useState} from \"react\";\nimport {type StoryCanvasData, useCanvasStore} from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport {DynamicEditor} from \"@clubmed/usg-chat-ui/molecules/RichText/DynamicEditor\";\nimport type {DocAIContext} from \"@clubmed/usg-chat-ui/core/interfaces\";\nimport {useChatApiClient, useChatConfig} from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport {useToast} from \"@clubmed/usg-chat-ui/molecules/Notifications/useToast\";\nimport {Button} from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport {Loader2, Send} from \"lucide-react\";\n\ninterface StoryBodyProps {\n storyData: StoryCanvasData;\n}\n\nfunction StoryBody({\n storyData,\n }: StoryBodyProps) {\n const {story} = storyData;\n const {projectKey} = useCanvasStore();\n const [isPublishing, setIsPublishing] = useState(false);\n const [publishedIssue, setPublishedIssue] = useState<{ key: string; url: string } | null>(null);\n const [editorMarkdown, setEditorMarkdown] = useState<string>(\"\");\n const {toast} = useToast();\n const {dbUserId} = useChatConfig();\n const apiClient = useChatApiClient();\n\n // Build AI context for the editor (must be before conditional return)\n const aiContext: DocAIContext = useMemo(() => {\n if (!storyData) {\n return {\n brief: undefined,\n projectKey: projectKey || undefined,\n story: {\n title: \"\",\n description: \"\",\n acceptance_criteria: [],\n story_points: null,\n priority: \"Medium\",\n labels: [],\n technical_considerations: null,\n },\n validation: undefined,\n };\n }\n\n const {story, validation, structured_brief} = storyData;\n\n // Extract brief from structured_brief if available\n const brief = structured_brief\n ? Object.entries(structured_brief)\n .map(([key, value]) => `${key.replace(/_/g, \" \")}: ${String(value)}`)\n .join(\"\\n\")\n : undefined;\n\n // Handle technical_considerations\n let technicalConsiderations: string | object | null = null;\n if (story.technical_considerations) {\n if (typeof story.technical_considerations === 'string') {\n technicalConsiderations = story.technical_considerations;\n } else {\n technicalConsiderations = JSON.stringify(story.technical_considerations);\n }\n }\n\n return {\n brief,\n projectKey: projectKey || undefined,\n story: {\n title: story.title,\n description: story.description,\n acceptance_criteria: story.acceptance_criteria || [],\n technical_considerations: technicalConsiderations,\n story_points: null, // story_points might not be in canvas data\n priority: story.priority || \"Medium\",\n labels: story.labels || [],\n },\n validation: validation ? {\n is_valid: validation.is_valid,\n completeness_score: validation.completeness_score,\n coherence_score: validation.coherence_score,\n style_alignment_score: validation.style_alignment_score,\n issues: validation.issues,\n suggestions: validation.suggestions,\n } : undefined,\n };\n }, [storyData, projectKey]);\n\n // Initialize editor markdown with initial content\n const initialMarkdown = useMemo(() => {\n const storyTitle = story.title || \"Story\";\n\n // If description already contains full markdown (starts with #), check if title is included\n if (story.description && story.description.trim().startsWith('#')) {\n // Check if the first heading matches the story title (case-insensitive, ignoring special chars)\n const firstLine = story.description.trim().split('\\n')[0];\n const normalizedTitle = storyTitle.toLowerCase().replace(/[^\\w\\s]/g, '').trim();\n const normalizedFirstHeading = firstLine.replace(/^#+\\s*/, '').toLowerCase().replace(/[^\\w\\s]/g, '').trim();\n\n // If title is already present in the description, return as-is\n if (normalizedFirstHeading === normalizedTitle || normalizedFirstHeading.includes(normalizedTitle) || normalizedTitle.includes(normalizedFirstHeading)) {\n return story.description;\n }\n\n // Otherwise, prepend the story title\n return `# ${storyTitle}\\n\\n${story.description}`;\n }\n\n // Otherwise, build markdown from structured fields (backward compatibility)\n let markdown = `# ${storyTitle}\\n\\n`;\n\n // Description (already in Markdown format from the LLM)\n if (story.description) {\n markdown += `${story.description}\\n\\n`;\n }\n\n return markdown;\n }, [story]);\n\n // Initialize editorMarkdown state with initial content\n useEffect(() => {\n if (!editorMarkdown && initialMarkdown) {\n setEditorMarkdown(initialMarkdown);\n }\n }, [editorMarkdown, initialMarkdown]); // Only run when initialMarkdown changes\n\n // Extract title from markdown (first heading)\n const extractTitleFromMarkdown = (markdown: string): string => {\n if (!markdown) return story.title || \"Story\";\n\n // Find the first heading (starts with #)\n const lines = markdown.trim().split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('#')) {\n // Extract text after # symbols\n const title = trimmed.replace(/^#+\\s*/, '').trim();\n if (title) {\n return title;\n }\n }\n }\n\n // Fallback to original title if no heading found\n return story.title || \"Story\";\n };\n\n const handlePublish = async () => {\n if (!projectKey) {\n toast({\n title: \"Erreur\",\n description: \"Aucun projet sélectionné. Veuillez configurer un projet dans les paramètres.\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsPublishing(true);\n try {\n // Extract title from editor content if available, otherwise use initial markdown\n const currentMarkdown = editorMarkdown || initialMarkdown;\n const updatedTitle = extractTitleFromMarkdown(currentMarkdown);\n\n // Create updated story object with the modified title and description\n const updatedStory = {\n ...story,\n title: updatedTitle,\n description: currentMarkdown, // Use the current editor content as description\n };\n\n const response = await apiClient.publishStory(updatedStory, projectKey, dbUserId || undefined);\n setPublishedIssue(response.jira_issue);\n toast({\n title: \"Succès\",\n description: `User story publiée avec succès : ${response.jira_issue.key}`,\n });\n } catch (error) {\n toast({\n title: \"Erreur\",\n description: error instanceof Error ? error.message : \"Échec de la publication de la user story\",\n variant: \"destructive\",\n });\n } finally {\n setIsPublishing(false);\n }\n };\n\n return (\n <div className=\"h-full flex flex-col overflow-hidden\">\n {/* Header avec bouton de publication */}\n <div className=\"flex items-center justify-end px-8 pt-6 pb-4 border-b border-border\">\n <div className=\"flex items-center gap-3\">\n {publishedIssue && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span>Publiée:</span>\n <a\n href={publishedIssue.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline font-medium\"\n >\n {publishedIssue.key}\n </a>\n </div>\n )}\n <Button\n onClick={handlePublish}\n disabled={isPublishing || !projectKey || !!publishedIssue}\n className=\"gap-2\"\n >\n {isPublishing ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\"/>\n Publication...\n </>\n ) : (\n <>\n <Send className=\"h-4 w-4\"/>\n Publier sur Jira\n </>\n )}\n </Button>\n </div>\n </div>\n\n {/* Editor */}\n <div className=\"flex-1 overflow-y-auto scroll-smooth\">\n <div className=\"px-8 pt-6 pb-16\">\n <div className=\"border border-border rounded-lg overflow-hidden shadow-sm\">\n <DynamicEditor\n initialMarkdown={initialMarkdown}\n editable={true}\n aiEnabled={true}\n aiContext={aiContext as Record<string, unknown>}\n onChange={(markdown: string) => {\n setEditorMarkdown(markdown);\n }}\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport function StoryCanvas() {\n const {storyData} = useCanvasStore();\n\n if (!storyData) {\n return (\n <div className=\"flex items-center justify-center h-full p-6\">\n <p className=\"text-muted-foreground\">No story data available</p>\n </div>\n );\n }\n\n return (\n <StoryBody storyData={storyData}/>\n );\n}\n"],"names":["StoryBody","storyData","story","projectKey","useCanvasStore","isPublishing","setIsPublishing","useState","publishedIssue","setPublishedIssue","editorMarkdown","setEditorMarkdown","toast","useToast","dbUserId","useChatConfig","apiClient","useChatApiClient","aiContext","useMemo","validation","structured_brief","brief","key","value","technicalConsiderations","initialMarkdown","storyTitle","firstLine","normalizedTitle","normalizedFirstHeading","markdown","useEffect","extractTitleFromMarkdown","lines","line","trimmed","title","handlePublish","currentMarkdown","updatedTitle","updatedStory","response","error","jsxs","jsx","Button","Fragment","Loader2","Send","DynamicEditor","StoryCanvas"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs as t, Fragment as f, jsx as e } from "react/jsx-runtime";
|
|
3
3
|
import { useState as a } from "react";
|
|
4
4
|
import { cn as s } from "../../utils/cn.js";
|
|
5
|
-
import { useToast as L } from "../../molecules/Notifications/
|
|
5
|
+
import { useToast as L } from "../../molecules/Notifications/useToast.js";
|
|
6
6
|
import { useCanvasStore as V } from "../../utils/canvas-store.js";
|
|
7
7
|
import { useChatApiClient as q } from "../../contexts/ChatContext.js";
|
|
8
8
|
import { Modal as B } from "../../molecules/Modals/Modal.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageActions.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/thumbs-down.js","../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/thumbs-up.js","../../../lib/organisms/chat/MessageActions.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17 14V2\", key: \"8ymqnk\" }],\n [\n \"path\",\n {\n d: \"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\",\n key: \"m61m77\"\n }\n ]\n];\nconst ThumbsDown = createLucideIcon(\"thumbs-down\", __iconNode);\n\nexport { __iconNode, ThumbsDown as default };\n//# sourceMappingURL=thumbs-down.js.map\n","/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M7 10v12\", key: \"1qc93n\" }],\n [\n \"path\",\n {\n d: \"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\",\n key: \"emmmcr\"\n }\n ]\n];\nconst ThumbsUp = createLucideIcon(\"thumbs-up\", __iconNode);\n\nexport { __iconNode, ThumbsUp as default };\n//# sourceMappingURL=thumbs-up.js.map\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { ChangeEvent } from \"react\";\nimport { Copy, RefreshCw, Check, Maximize2, ThumbsUp, ThumbsDown, X } from \"lucide-react\";\nimport { cn } from \"@clubmed/usg-chat-ui/utils/cn\";\nimport { useToast } from \"@clubmed/usg-chat-ui/molecules/Notifications/use-toast\";\nimport { useCanvasStore } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { useChatApiClient } from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport { Modal } from \"@clubmed/usg-chat-ui/molecules/Modals/Modal\";\nimport { Button } from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport { Textarea } from \"@clubmed/usg-chat-ui/molecules/Textareas/Textarea\";\n\ninterface MessageActionsProps {\n content: string;\n messageId?: string;\n storyId?: string;\n onRegenerate?: () => void;\n responseType?: \"message\" | \"story\" | \"api_answer\" | \"followup_questions\" | \"release_note\";\n canvasData?: Record<string, unknown>;\n className?: string;\n}\n\nexport function MessageActions({ \n content, \n messageId,\n storyId,\n onRegenerate, \n responseType,\n canvasData,\n className \n}: MessageActionsProps) {\n const [copied, setCopied] = useState(false);\n const [feedbackGiven, setFeedbackGiven] = useState<\"positive\" | \"negative\" | null>(null);\n const [showFeedbackModal, setShowFeedbackModal] = useState(false);\n const [pendingRating, setPendingRating] = useState<\"positive\" | \"negative\" | null>(null);\n const [feedbackComment, setFeedbackComment] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { toast } = useToast();\n const { openApiDocsCanvas } = useCanvasStore();\n const apiClient = useChatApiClient();\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n toast({\n title: \"Copié\",\n description: \"Message copié dans le presse-papiers\",\n });\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n console.error(\"Failed to copy:\", error);\n toast({\n title: \"Erreur\",\n description: \"Impossible de copier le message\",\n variant: \"destructive\",\n });\n }\n };\n\n const handleOpenApiCanvas = () => {\n if (canvasData && responseType === \"api_answer\") {\n const apiData = canvasData as {\n answer?: string;\n sources?: Array<{ title: string; href: string; score?: number }>;\n };\n \n if (apiData.answer || apiData.sources) {\n openApiDocsCanvas({\n answer: apiData.answer || content,\n sources: apiData.sources || [],\n });\n }\n }\n };\n\n const handleFeedbackClick = (rating: \"positive\" | \"negative\") => {\n if (feedbackGiven) return; // Already gave feedback\n setPendingRating(rating);\n setShowFeedbackModal(true);\n };\n\n const submitFeedback = async (withComment: boolean) => {\n if (!pendingRating) return;\n \n setIsSubmitting(true);\n try {\n await apiClient.submitFeedback({\n messageId,\n storyId,\n rating: pendingRating,\n comment: withComment ? feedbackComment : undefined,\n responseType: responseType as \"story\" | \"release_note\" | \"api_answer\" | \"message\" | undefined,\n });\n \n setFeedbackGiven(pendingRating);\n setShowFeedbackModal(false);\n setFeedbackComment(\"\");\n \n toast({\n title: \"Merci !\",\n description: \"Votre feedback a été enregistré\",\n });\n } catch (error) {\n console.error(\"Failed to submit feedback:\", error);\n toast({\n title: \"Erreur\",\n description: \"Impossible d'enregistrer le feedback\",\n variant: \"destructive\",\n });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleModalClose = () => {\n setShowFeedbackModal(false);\n setPendingRating(null);\n setFeedbackComment(\"\");\n };\n\n return (\n <>\n <div className={cn(\"flex items-center gap-1.5 mt-3 pt-2 border-t border-border\", className)}>\n <button\n onClick={handleCopy}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Copier le message\"\n aria-label=\"Copier le message\"\n >\n {copied ? (\n <>\n <Check className=\"h-3.5 w-3.5 text-positive-foreground\" />\n <span className=\"text-xs font-medium text-positive-foreground\">Copié</span>\n </>\n ) : (\n <>\n <Copy className=\"h-3.5 w-3.5\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Copier</span>\n </>\n )}\n </button>\n \n {onRegenerate && (\n <button\n onClick={onRegenerate}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Régénérer la réponse\"\n aria-label=\"Régénérer la réponse\"\n >\n <RefreshCw className=\"h-3.5 w-3.5 group-hover:rotate-180 transition-transform duration-500\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Régénérer</span>\n </button>\n )}\n \n {responseType === \"api_answer\" && canvasData && (\n <button\n onClick={handleOpenApiCanvas}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Ouvrir Canva\"\n aria-label=\"Ouvrir Canva\"\n >\n <Maximize2 className=\"h-3.5 w-3.5 group-hover:scale-110 transition-transform duration-200\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Ouvrir Canva</span>\n </button>\n )}\n\n {/* Feedback buttons - separator */}\n <div className=\"mx-1 h-4 w-px bg-muted-foreground/20\" />\n\n {/* Thumbs Up */}\n <button\n onClick={() => handleFeedbackClick(\"positive\")}\n disabled={feedbackGiven !== null}\n className={cn(\n \"group flex items-center gap-1 px-2 py-1.5 rounded-md transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\",\n feedbackGiven === \"positive\"\n ? \"bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400\"\n : feedbackGiven !== null\n ? \"opacity-50 cursor-not-allowed text-muted-foreground\"\n : \"hover:bg-muted/60 text-muted-foreground hover:text-green-600 dark:hover:text-green-400 hover:scale-105\"\n )}\n title=\"Réponse utile\"\n aria-label=\"Réponse utile\"\n >\n <ThumbsUp className={cn(\n \"h-3.5 w-3.5\",\n feedbackGiven === \"positive\" && \"fill-current\"\n )} />\n </button>\n\n {/* Thumbs Down */}\n <button\n onClick={() => handleFeedbackClick(\"negative\")}\n disabled={feedbackGiven !== null}\n className={cn(\n \"group flex items-center gap-1 px-2 py-1.5 rounded-md transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\",\n feedbackGiven === \"negative\"\n ? \"bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400\"\n : feedbackGiven !== null\n ? \"opacity-50 cursor-not-allowed text-muted-foreground\"\n : \"hover:bg-muted/60 text-muted-foreground hover:text-red-600 dark:hover:text-red-400 hover:scale-105\"\n )}\n title=\"Réponse non utile\"\n aria-label=\"Réponse non utile\"\n >\n <ThumbsDown className={cn(\n \"h-3.5 w-3.5\",\n feedbackGiven === \"negative\" && \"fill-current\"\n )} />\n </button>\n </div>\n\n <Modal\n isOpen={showFeedbackModal}\n onClose={handleModalClose}\n size=\"small\"\n showCloseButton={false}\n className=\"w-[calc(100vw-2rem)] max-w-md\"\n >\n <div className=\"relative space-y-4\">\n <button\n type=\"button\"\n onClick={handleModalClose}\n className=\"absolute right-0 top-0 text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Fermer\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n\n <div\n className={cn(\n \"flex items-start gap-3 rounded-lg border px-4 py-3 sm:px-5 sm:py-4 pt-4\",\n pendingRating === \"positive\"\n ? \"border-green-200 bg-green-50 dark:bg-green-950/20 text-green-700 dark:text-green-300\"\n : \"border-red-200 bg-red-50 dark:bg-red-950/20 text-red-700 dark:text-red-300\"\n )}\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-white/70 dark:bg-background/30\">\n {pendingRating === \"positive\" ? (\n <ThumbsUp className=\"h-4 w-4 fill-current\" />\n ) : (\n <ThumbsDown className=\"h-4 w-4 fill-current\" />\n )}\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-sm font-semibold\">\n {pendingRating === \"positive\"\n ? \"Merci pour votre feedback !\"\n : \"Aidez-nous à nous améliorer\"}\n </p>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n Un commentaire pour nous aider ?\n </p>\n </div>\n </div>\n\n <Textarea\n placeholder=\"Votre commentaire (optionnel)...\"\n value={feedbackComment}\n onChange={(event: ChangeEvent<HTMLTextAreaElement>) =>\n setFeedbackComment(event.target.value)\n }\n className=\"min-h-[80px] max-h-[150px] w-full resize-none text-sm box-border\"\n disabled={isSubmitting}\n />\n\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => submitFeedback(false)}\n disabled={isSubmitting}\n className=\"w-full sm:w-auto text-muted-foreground hover:text-foreground\"\n >\n Passer\n </Button>\n <Button\n size=\"sm\"\n onClick={() => submitFeedback(true)}\n disabled={isSubmitting || !feedbackComment.trim()}\n className={cn(\n \"w-full sm:w-auto\",\n pendingRating === \"positive\"\n ? \"bg-green-600 hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600\"\n : \"bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600\"\n )}\n >\n {isSubmitting ? \"Envoi...\" : \"Envoyer\"}\n </Button>\n </div>\n </div>\n </Modal>\n </>\n );\n}\n"],"names":["__iconNode","ThumbsDown","createLucideIcon","ThumbsUp","MessageActions","content","messageId","storyId","onRegenerate","responseType","canvasData","className","copied","setCopied","useState","feedbackGiven","setFeedbackGiven","showFeedbackModal","setShowFeedbackModal","pendingRating","setPendingRating","feedbackComment","setFeedbackComment","isSubmitting","setIsSubmitting","toast","useToast","openApiDocsCanvas","useCanvasStore","apiClient","useChatApiClient","handleCopy","error","handleOpenApiCanvas","apiData","handleFeedbackClick","rating","submitFeedback","withComment","handleModalClose","jsxs","Fragment","cn","jsx","Check","Copy","RefreshCw","Maximize2","Modal","Textarea","event","Button"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,IAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AACA,GACMC,IAAaC,EAAiB,eAAeF,CAAU;ACnB7D;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,IAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AACA,GACMG,IAAWD,EAAiB,aAAaF,CAAU;ACIlD,SAASI,GAAe;AAAA,EAC7B,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AACF,GAAwB;AACtB,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAS,EAAK,GACpC,CAACC,GAAeC,CAAgB,IAAIF,EAAyC,IAAI,GACjF,CAACG,GAAmBC,CAAoB,IAAIJ,EAAS,EAAK,GAC1D,CAACK,GAAeC,CAAgB,IAAIN,EAAyC,IAAI,GACjF,CAACO,GAAiBC,CAAkB,IAAIR,EAAS,EAAE,GACnD,CAACS,GAAcC,CAAe,IAAIV,EAAS,EAAK,GAChD,EAAE,OAAAW,EAAA,IAAUC,EAAA,GACZ,EAAE,mBAAAC,EAAA,IAAsBC,EAAA,GACxBC,IAAYC,EAAA,GAEZC,IAAa,YAAY;AAC7B,QAAI;AACF,YAAM,UAAU,UAAU,UAAU1B,CAAO,GAC3CQ,EAAU,EAAI,GACdY,EAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa;AAAA,MAAA,CACd,GACD,WAAW,MAAMZ,EAAU,EAAK,GAAG,GAAI;AAAA,IACzC,SAASmB,GAAO;AACd,cAAQ,MAAM,mBAAmBA,CAAK,GACtCP,EAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAAA,EACF,GAEMQ,IAAsB,MAAM;AAChC,QAAIvB,KAAcD,MAAiB,cAAc;AAC/C,YAAMyB,IAAUxB;AAKhB,OAAIwB,EAAQ,UAAUA,EAAQ,YAC5BP,EAAkB;AAAA,QAChB,QAAQO,EAAQ,UAAU7B;AAAA,QAC1B,SAAS6B,EAAQ,WAAW,CAAA;AAAA,MAAC,CAC9B;AAAA,IAEL;AAAA,EACF,GAEMC,IAAsB,CAACC,MAAoC;AAC/D,IAAIrB,MACJK,EAAiBgB,CAAM,GACvBlB,EAAqB,EAAI;AAAA,EAC3B,GAEMmB,IAAiB,OAAOC,MAAyB;AACrD,QAAKnB,GAEL;AAAA,MAAAK,EAAgB,EAAI;AACpB,UAAI;AACF,cAAMK,EAAU,eAAe;AAAA,UAC7B,WAAAvB;AAAA,UACA,SAAAC;AAAA,UACA,QAAQY;AAAA,UACR,SAASmB,IAAcjB,IAAkB;AAAA,UACzC,cAAAZ;AAAA,QAAA,CACD,GAEDO,EAAiBG,CAAa,GAC9BD,EAAqB,EAAK,GAC1BI,EAAmB,EAAE,GAErBG,EAAM;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AAAA,MACH,SAASO,GAAO;AACd,gBAAQ,MAAM,8BAA8BA,CAAK,GACjDP,EAAM;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,QAAA,CACV;AAAA,MACH,UAAA;AACE,QAAAD,EAAgB,EAAK;AAAA,MACvB;AAAA;AAAA,EACF,GAEMe,IAAmB,MAAM;AAC7B,IAAArB,EAAqB,EAAK,GAC1BE,EAAiB,IAAI,GACrBE,EAAmB,EAAE;AAAA,EACvB;AAEA,SACE,gBAAAkB,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAD,EAAC,OAAA,EAAI,WAAWE,EAAG,8DAA8D/B,CAAS,GACxF,UAAA;AAAA,MAAA,gBAAAgC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASZ;AAAA,UACT,WAAU;AAAA,UACV,OAAM;AAAA,UACN,cAAW;AAAA,UAEV,cACC,gBAAAS,EAAAC,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAE,EAACC,GAAA,EAAM,WAAU,uCAAA,CAAuC;AAAA,YACxD,gBAAAD,EAAC,QAAA,EAAK,WAAU,gDAA+C,UAAA,QAAA,CAAK;AAAA,UAAA,EAAA,CACtE,IAEA,gBAAAH,EAAAC,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAE,EAACE,GAAA,EAAK,WAAU,cAAA,CAAc;AAAA,YAC9B,gBAAAF,EAAC,QAAA,EAAK,WAAU,wCAAuC,UAAA,SAAA,CAAM;AAAA,UAAA,EAAA,CAC/D;AAAA,QAAA;AAAA,MAAA;AAAA,MAIHnC,KACC,gBAAAgC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAShC;AAAA,UACT,WAAU;AAAA,UACV,OAAM;AAAA,UACN,cAAW;AAAA,UAEX,UAAA;AAAA,YAAA,gBAAAmC,EAACG,GAAA,EAAU,WAAU,uEAAA,CAAuE;AAAA,YAC5F,gBAAAH,EAAC,QAAA,EAAK,WAAU,wCAAuC,UAAA,YAAA,CAAS;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAInElC,MAAiB,gBAAgBC,KAChC,gBAAA8B;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASP;AAAA,UACT,WAAU;AAAA,UACV,OAAM;AAAA,UACN,cAAW;AAAA,UAEX,UAAA;AAAA,YAAA,gBAAAU,EAACI,GAAA,EAAU,WAAU,sEAAA,CAAsE;AAAA,YAC3F,gBAAAJ,EAAC,QAAA,EAAK,WAAU,wCAAuC,UAAA,eAAA,CAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAKvE,gBAAAA,EAAC,OAAA,EAAI,WAAU,uCAAA,CAAuC;AAAA,MAGtD,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAMR,EAAoB,UAAU;AAAA,UAC7C,UAAUpB,MAAkB;AAAA,UAC5B,WAAW2B;AAAA,YACT;AAAA,YACA3B,MAAkB,aACd,yEACAA,MAAkB,OAClB,wDACA;AAAA,UAAA;AAAA,UAEN,OAAM;AAAA,UACN,cAAW;AAAA,UAEX,UAAA,gBAAA4B,EAACxC,KAAS,WAAWuC;AAAA,YACnB;AAAA,YACA3B,MAAkB,cAAc;AAAA,UAAA,EAClC,CAAG;AAAA,QAAA;AAAA,MAAA;AAAA,MAIL,gBAAA4B;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAMR,EAAoB,UAAU;AAAA,UAC7C,UAAUpB,MAAkB;AAAA,UAC5B,WAAW2B;AAAA,YACT;AAAA,YACA3B,MAAkB,aACd,iEACAA,MAAkB,OAClB,wDACA;AAAA,UAAA;AAAA,UAEN,OAAM;AAAA,UACN,cAAW;AAAA,UAEX,UAAA,gBAAA4B,EAAC1C,KAAW,WAAWyC;AAAA,YACrB;AAAA,YACA3B,MAAkB,cAAc;AAAA,UAAA,EAClC,CAAG;AAAA,QAAA;AAAA,MAAA;AAAA,IACL,GACF;AAAA,IAEA,gBAAA4B;AAAA,MAACK;AAAA,MAAA;AAAA,QACC,QAAQ/B;AAAA,QACR,SAASsB;AAAA,QACT,MAAK;AAAA,QACL,iBAAiB;AAAA,QACjB,WAAU;AAAA,QAEV,UAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,UAAA,gBAAAG;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAASJ;AAAA,cACT,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,UAAA,gBAAAI,EAAC,GAAA,EAAE,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzB,gBAAAH;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWE;AAAA,gBACT;AAAA,gBACAvB,MAAkB,aACd,yFACA;AAAA,cAAA;AAAA,cAGN,UAAA;AAAA,gBAAA,gBAAAwB,EAAC,OAAA,EAAI,WAAU,2FACZ,UAAAxB,MAAkB,aACjB,gBAAAwB,EAACxC,GAAA,EAAS,WAAU,uBAAA,CAAuB,IAE3C,gBAAAwC,EAAC1C,GAAA,EAAW,WAAU,wBAAuB,GAEjD;AAAA,gBACA,gBAAAuC,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,kBAAA,gBAAAG,EAAC,OAAE,WAAU,yBACV,UAAAxB,MAAkB,aACf,gCACA,+BACN;AAAA,kBACA,gBAAAwB,EAAC,KAAA,EAAE,WAAU,4CAA2C,UAAA,mCAAA,CAExD;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGF,gBAAAA;AAAA,YAACM;AAAA,YAAA;AAAA,cACC,aAAY;AAAA,cACZ,OAAO5B;AAAA,cACP,UAAU,CAAC6B,MACT5B,EAAmB4B,EAAM,OAAO,KAAK;AAAA,cAEvC,WAAU;AAAA,cACV,UAAU3B;AAAA,YAAA;AAAA,UAAA;AAAA,UAGZ,gBAAAiB,EAAC,OAAA,EAAI,WAAU,0DACb,UAAA;AAAA,YAAA,gBAAAG;AAAA,cAACQ;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,SAAS,MAAMd,EAAe,EAAK;AAAA,gBACnC,UAAUd;AAAA,gBACV,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGD,gBAAAoB;AAAA,cAACQ;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAMd,EAAe,EAAI;AAAA,gBAClC,UAAUd,KAAgB,CAACF,EAAgB,KAAA;AAAA,gBAC3C,WAAWqB;AAAA,kBACT;AAAA,kBACAvB,MAAkB,aACd,8EACA;AAAA,gBAAA;AAAA,gBAGL,cAAe,aAAa;AAAA,cAAA;AAAA,YAAA;AAAA,UAC/B,EAAA,CACF;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"MessageActions.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/thumbs-down.js","../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/thumbs-up.js","../../../lib/organisms/chat/MessageActions.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17 14V2\", key: \"8ymqnk\" }],\n [\n \"path\",\n {\n d: \"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\",\n key: \"m61m77\"\n }\n ]\n];\nconst ThumbsDown = createLucideIcon(\"thumbs-down\", __iconNode);\n\nexport { __iconNode, ThumbsDown as default };\n//# sourceMappingURL=thumbs-down.js.map\n","/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M7 10v12\", key: \"1qc93n\" }],\n [\n \"path\",\n {\n d: \"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\",\n key: \"emmmcr\"\n }\n ]\n];\nconst ThumbsUp = createLucideIcon(\"thumbs-up\", __iconNode);\n\nexport { __iconNode, ThumbsUp as default };\n//# sourceMappingURL=thumbs-up.js.map\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { ChangeEvent } from \"react\";\nimport { Copy, RefreshCw, Check, Maximize2, ThumbsUp, ThumbsDown, X } from \"lucide-react\";\nimport { cn } from \"@clubmed/usg-chat-ui/utils/cn\";\nimport { useToast } from \"@clubmed/usg-chat-ui/molecules/Notifications/useToast\";\nimport { useCanvasStore } from \"@clubmed/usg-chat-ui/utils/canvas-store\";\nimport { useChatApiClient } from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport { Modal } from \"@clubmed/usg-chat-ui/molecules/Modals/Modal\";\nimport { Button } from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport { Textarea } from \"@clubmed/usg-chat-ui/molecules/Textareas/Textarea\";\n\ninterface MessageActionsProps {\n content: string;\n messageId?: string;\n storyId?: string;\n onRegenerate?: () => void;\n responseType?: \"message\" | \"story\" | \"api_answer\" | \"followup_questions\" | \"release_note\";\n canvasData?: Record<string, unknown>;\n className?: string;\n}\n\nexport function MessageActions({ \n content, \n messageId,\n storyId,\n onRegenerate, \n responseType,\n canvasData,\n className \n}: MessageActionsProps) {\n const [copied, setCopied] = useState(false);\n const [feedbackGiven, setFeedbackGiven] = useState<\"positive\" | \"negative\" | null>(null);\n const [showFeedbackModal, setShowFeedbackModal] = useState(false);\n const [pendingRating, setPendingRating] = useState<\"positive\" | \"negative\" | null>(null);\n const [feedbackComment, setFeedbackComment] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { toast } = useToast();\n const { openApiDocsCanvas } = useCanvasStore();\n const apiClient = useChatApiClient();\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n toast({\n title: \"Copié\",\n description: \"Message copié dans le presse-papiers\",\n });\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n console.error(\"Failed to copy:\", error);\n toast({\n title: \"Erreur\",\n description: \"Impossible de copier le message\",\n variant: \"destructive\",\n });\n }\n };\n\n const handleOpenApiCanvas = () => {\n if (canvasData && responseType === \"api_answer\") {\n const apiData = canvasData as {\n answer?: string;\n sources?: Array<{ title: string; href: string; score?: number }>;\n };\n \n if (apiData.answer || apiData.sources) {\n openApiDocsCanvas({\n answer: apiData.answer || content,\n sources: apiData.sources || [],\n });\n }\n }\n };\n\n const handleFeedbackClick = (rating: \"positive\" | \"negative\") => {\n if (feedbackGiven) return; // Already gave feedback\n setPendingRating(rating);\n setShowFeedbackModal(true);\n };\n\n const submitFeedback = async (withComment: boolean) => {\n if (!pendingRating) return;\n \n setIsSubmitting(true);\n try {\n await apiClient.submitFeedback({\n messageId,\n storyId,\n rating: pendingRating,\n comment: withComment ? feedbackComment : undefined,\n responseType: responseType as \"story\" | \"release_note\" | \"api_answer\" | \"message\" | undefined,\n });\n \n setFeedbackGiven(pendingRating);\n setShowFeedbackModal(false);\n setFeedbackComment(\"\");\n \n toast({\n title: \"Merci !\",\n description: \"Votre feedback a été enregistré\",\n });\n } catch (error) {\n console.error(\"Failed to submit feedback:\", error);\n toast({\n title: \"Erreur\",\n description: \"Impossible d'enregistrer le feedback\",\n variant: \"destructive\",\n });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleModalClose = () => {\n setShowFeedbackModal(false);\n setPendingRating(null);\n setFeedbackComment(\"\");\n };\n\n return (\n <>\n <div className={cn(\"flex items-center gap-1.5 mt-3 pt-2 border-t border-border\", className)}>\n <button\n onClick={handleCopy}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Copier le message\"\n aria-label=\"Copier le message\"\n >\n {copied ? (\n <>\n <Check className=\"h-3.5 w-3.5 text-positive-foreground\" />\n <span className=\"text-xs font-medium text-positive-foreground\">Copié</span>\n </>\n ) : (\n <>\n <Copy className=\"h-3.5 w-3.5\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Copier</span>\n </>\n )}\n </button>\n \n {onRegenerate && (\n <button\n onClick={onRegenerate}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Régénérer la réponse\"\n aria-label=\"Régénérer la réponse\"\n >\n <RefreshCw className=\"h-3.5 w-3.5 group-hover:rotate-180 transition-transform duration-500\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Régénérer</span>\n </button>\n )}\n \n {responseType === \"api_answer\" && canvasData && (\n <button\n onClick={handleOpenApiCanvas}\n className=\"group flex items-center gap-1.5 px-2.5 py-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\"\n title=\"Ouvrir Canva\"\n aria-label=\"Ouvrir Canva\"\n >\n <Maximize2 className=\"h-3.5 w-3.5 group-hover:scale-110 transition-transform duration-200\" />\n <span className=\"text-xs font-medium hidden sm:inline\">Ouvrir Canva</span>\n </button>\n )}\n\n {/* Feedback buttons - separator */}\n <div className=\"mx-1 h-4 w-px bg-muted-foreground/20\" />\n\n {/* Thumbs Up */}\n <button\n onClick={() => handleFeedbackClick(\"positive\")}\n disabled={feedbackGiven !== null}\n className={cn(\n \"group flex items-center gap-1 px-2 py-1.5 rounded-md transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\",\n feedbackGiven === \"positive\"\n ? \"bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400\"\n : feedbackGiven !== null\n ? \"opacity-50 cursor-not-allowed text-muted-foreground\"\n : \"hover:bg-muted/60 text-muted-foreground hover:text-green-600 dark:hover:text-green-400 hover:scale-105\"\n )}\n title=\"Réponse utile\"\n aria-label=\"Réponse utile\"\n >\n <ThumbsUp className={cn(\n \"h-3.5 w-3.5\",\n feedbackGiven === \"positive\" && \"fill-current\"\n )} />\n </button>\n\n {/* Thumbs Down */}\n <button\n onClick={() => handleFeedbackClick(\"negative\")}\n disabled={feedbackGiven !== null}\n className={cn(\n \"group flex items-center gap-1 px-2 py-1.5 rounded-md transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background\",\n feedbackGiven === \"negative\"\n ? \"bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400\"\n : feedbackGiven !== null\n ? \"opacity-50 cursor-not-allowed text-muted-foreground\"\n : \"hover:bg-muted/60 text-muted-foreground hover:text-red-600 dark:hover:text-red-400 hover:scale-105\"\n )}\n title=\"Réponse non utile\"\n aria-label=\"Réponse non utile\"\n >\n <ThumbsDown className={cn(\n \"h-3.5 w-3.5\",\n feedbackGiven === \"negative\" && \"fill-current\"\n )} />\n </button>\n </div>\n\n <Modal\n isOpen={showFeedbackModal}\n onClose={handleModalClose}\n size=\"small\"\n showCloseButton={false}\n className=\"w-[calc(100vw-2rem)] max-w-md\"\n >\n <div className=\"relative space-y-4\">\n <button\n type=\"button\"\n onClick={handleModalClose}\n className=\"absolute right-0 top-0 text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Fermer\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n\n <div\n className={cn(\n \"flex items-start gap-3 rounded-lg border px-4 py-3 sm:px-5 sm:py-4 pt-4\",\n pendingRating === \"positive\"\n ? \"border-green-200 bg-green-50 dark:bg-green-950/20 text-green-700 dark:text-green-300\"\n : \"border-red-200 bg-red-50 dark:bg-red-950/20 text-red-700 dark:text-red-300\"\n )}\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-white/70 dark:bg-background/30\">\n {pendingRating === \"positive\" ? (\n <ThumbsUp className=\"h-4 w-4 fill-current\" />\n ) : (\n <ThumbsDown className=\"h-4 w-4 fill-current\" />\n )}\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-sm font-semibold\">\n {pendingRating === \"positive\"\n ? \"Merci pour votre feedback !\"\n : \"Aidez-nous à nous améliorer\"}\n </p>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n Un commentaire pour nous aider ?\n </p>\n </div>\n </div>\n\n <Textarea\n placeholder=\"Votre commentaire (optionnel)...\"\n value={feedbackComment}\n onChange={(event: ChangeEvent<HTMLTextAreaElement>) =>\n setFeedbackComment(event.target.value)\n }\n className=\"min-h-[80px] max-h-[150px] w-full resize-none text-sm box-border\"\n disabled={isSubmitting}\n />\n\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => submitFeedback(false)}\n disabled={isSubmitting}\n className=\"w-full sm:w-auto text-muted-foreground hover:text-foreground\"\n >\n Passer\n </Button>\n <Button\n size=\"sm\"\n onClick={() => submitFeedback(true)}\n disabled={isSubmitting || !feedbackComment.trim()}\n className={cn(\n \"w-full sm:w-auto\",\n pendingRating === \"positive\"\n ? \"bg-green-600 hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600\"\n : \"bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600\"\n )}\n >\n {isSubmitting ? \"Envoi...\" : \"Envoyer\"}\n </Button>\n </div>\n </div>\n </Modal>\n </>\n );\n}\n"],"names":["__iconNode","ThumbsDown","createLucideIcon","ThumbsUp","MessageActions","content","messageId","storyId","onRegenerate","responseType","canvasData","className","copied","setCopied","useState","feedbackGiven","setFeedbackGiven","showFeedbackModal","setShowFeedbackModal","pendingRating","setPendingRating","feedbackComment","setFeedbackComment","isSubmitting","setIsSubmitting","toast","useToast","openApiDocsCanvas","useCanvasStore","apiClient","useChatApiClient","handleCopy","error","handleOpenApiCanvas","apiData","handleFeedbackClick","rating","submitFeedback","withComment","handleModalClose","jsxs","Fragment","cn","jsx","Check","Copy","RefreshCw","Maximize2","Modal","Textarea","event","Button"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useState as k, useCallback as N } from "react";
|
|
3
3
|
import { parseChatCommand as Q, shouldHandleCommand as V, getCommandHelp as X } from "../../../utils/chat-commands.js";
|
|
4
|
-
import { useToast as Y } from "../../../molecules/Notifications/
|
|
4
|
+
import { useToast as Y } from "../../../molecules/Notifications/useToast.js";
|
|
5
5
|
import { useCanvasStore as Z } from "../../../utils/canvas-store.js";
|
|
6
6
|
import { useChatApiClient as ee, useChatConfig as te } from "../../../contexts/ChatContext.js";
|
|
7
7
|
import { useConversations as se } from "./useConversations.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.js","sources":["../../../../lib/organisms/chat/hooks/useChat.ts"],"sourcesContent":["\"use client\";\n\nimport {useCallback, useState} from \"react\";\nimport {getCommandHelp, parseChatCommand, shouldHandleCommand} from \"../../../utils/chat-commands\";\nimport {useToast} from \"../../../molecules/Notifications/use-toast\";\nimport type {PromptInputMessage} from \"@clubmed/usg-chat-ui/molecules/AiElements/PromptInput\";\nimport {useCanvasStore} from \"../../../utils/canvas-store\";\nimport type {ChatMessage} from \"../types\";\nimport type {ChatCanvasResponse} from \"@clubmed/usg-chat-ui/core/interfaces/ChatCanvas\";\nimport {useChatApiClient, useChatConfig} from \"../../../contexts/ChatContext\";\nimport {useConversations} from \"./useConversations\";\nimport {useChatJira} from \"@clubmed/usg-chat-ui/contexts/ChatJiraContext\";\nimport {useChatPreferences} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences\";\nimport {useChatSyncUserSettings} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings\";\nimport {useChatKeyboardsShortcuts} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts\";\n\nconst mapCanvasSources = (sources: ChatCanvasResponse[\"sources\"]) =>\n sources?.map((source) => ({\n href: source.href || source.url || \"#\",\n title: source.title || \"Source\",\n }));\n\nconst mapCanvasReasoning = (reasoning: ChatCanvasResponse[\"reasoning\"]) => {\n if (!reasoning) {\n return undefined;\n }\n\n if (typeof reasoning === \"string\") {\n return {content: reasoning, duration: 0};\n }\n\n return {\n content: reasoning.content ?? \"\",\n duration: reasoning.duration ?? 0,\n };\n};\n\nconst buildAssistantResponseParts = (data: ChatCanvasResponse) => {\n if (data.response_type === \"auth_required\") {\n throw new Error(\"Cannot build assistant response for auth-required payload\");\n }\n\n const id = `assistant-${Date.now()}`;\n const version: ChatMessage[\"versions\"][number] = {\n id,\n content: data.content || \"Aucune réponse disponible\",\n responseType: data.response_type,\n canvasData: data.canvas_data,\n followupQuestions: data.followup_questions,\n };\n\n return {\n key: id,\n version,\n sources: mapCanvasSources(data.sources),\n reasoning: mapCanvasReasoning(data.reasoning),\n };\n};\n\nexport function useChat() {\n const {toast} = useToast();\n const apiClient = useChatApiClient();\n const {setJiraConfigured, setJiraAuthSettings} = useChatJira();\n\n const {\n user,\n dbUserId,\n } = useChatConfig();\n\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [localInput, setLocalInput] = useState(\"\");\n\n const {\n chatMessages,\n setChatMessages,\n currentConversationId,\n sidebarRefreshTrigger,\n isLoadingMessage,\n setIsLoadingMessage,\n loadConversation,\n handleNewConversation,\n saveConversation,\n } = useConversations();\n\n useChatSyncUserSettings();\n useChatKeyboardsShortcuts();\n useChatPreferences();\n\n const {\n canvasType,\n projectKey,\n releaseNoteSettings,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n } = useCanvasStore();\n\n const handleSubmit = useCallback(\n async (message: PromptInputMessage) => {\n\n if (!message.text?.trim()) {\n return;\n }\n\n const userMessage = message.text.trim();\n const parsed = parseChatCommand(userMessage);\n\n if (shouldHandleCommand(parsed)) {\n if (parsed.command === \"settings\") {\n setSettingsOpen(true);\n return;\n }\n\n if (parsed.command === \"help\") {\n const helpMessage: ChatMessage = {\n key: `assistant-${Date.now()}`,\n from: \"assistant\",\n versions: [\n {\n id: `assistant-${Date.now()}`,\n content: getCommandHelp(),\n responseType: \"message\",\n },\n ],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n };\n setChatMessages((prev) => [...prev, helpMessage]);\n setLocalInput(\"\");\n return;\n }\n\n if (parsed.command === \"clear\") {\n setChatMessages([]);\n toast({\n title: \"Cleared\",\n description: \"Conversation history cleared\",\n });\n setLocalInput(\"\");\n return;\n }\n }\n\n const newUserMessage: ChatMessage = {\n key: `user-${Date.now()}`,\n from: \"user\",\n versions: [\n {\n id: `user-${Date.now()}`,\n content: userMessage,\n },\n ],\n avatar: \"https://github.com/haydenbleasel.png\",\n name: \"User\",\n };\n setChatMessages((prev) => [...prev, newUserMessage]);\n setLocalInput(\"\");\n\n setTimeout(() => {\n saveConversation();\n }, 200);\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: chatMessages.flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n ),\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setChatMessages((prev) => prev.slice(0, -1));\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {key, version, sources, reasoning} = buildAssistantResponseParts(data);\n\n const assistantMessage: ChatMessage = {\n key,\n from: \"assistant\",\n versions: [version],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n sources,\n reasoning,\n };\n\n setChatMessages((prev) => [...prev, assistantMessage]);\n setIsLoadingMessage(false);\n\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Chat error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Error\",\n description: \"Failed to get response. Please try again.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraAuthSettings,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleRegenerate = useCallback(\n async (messageKey: string) => {\n const messageIndex = chatMessages.findIndex((msg) => msg.key === messageKey);\n if (messageIndex === -1) return;\n\n const previousMessage = messageIndex > 0 ? chatMessages[messageIndex - 1] : null;\n const userMessage = previousMessage?.versions[0]?.content || \"\";\n\n if (!userMessage) {\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer : aucun message précédent trouvé\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const history = chatMessages.slice(0, messageIndex).flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n );\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: history,\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {version, sources, reasoning} = buildAssistantResponseParts(data);\n\n setChatMessages((prev) =>\n prev.map((msg) => {\n if (msg.key === messageKey) {\n return {\n ...msg,\n versions: [...msg.versions, version],\n sources,\n reasoning,\n };\n }\n return msg;\n })\n );\n\n setIsLoadingMessage(false);\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Regenerate error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer la réponse. Veuillez réessayer.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleFollowupClick = useCallback((question: string) => {\n setLocalInput(question);\n }, []);\n\n const emptyStateGreeting = user?.userName\n ? `Bonjour ${user.userName.split(\" \")[0]} 👋`\n : undefined;\n\n return {\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n emptyStateGreeting\n };\n}\n"],"names":["mapCanvasSources","sources","source","mapCanvasReasoning","reasoning","buildAssistantResponseParts","data","id","version","useChat","toast","useToast","apiClient","useChatApiClient","setJiraConfigured","setJiraAuthSettings","useChatJira","user","dbUserId","useChatConfig","settingsOpen","setSettingsOpen","useState","sidebarOpen","setSidebarOpen","localInput","setLocalInput","chatMessages","setChatMessages","currentConversationId","sidebarRefreshTrigger","isLoadingMessage","setIsLoadingMessage","loadConversation","handleNewConversation","saveConversation","useConversations","useChatSyncUserSettings","useChatKeyboardsShortcuts","useChatPreferences","canvasType","projectKey","releaseNoteSettings","isFullscreen","canvasWidth","isResizing","resizeWidth","useCanvasStore","handleSubmit","useCallback","message","_a","userMessage","parsed","parseChatCommand","shouldHandleCommand","helpMessage","getCommandHelp","prev","newUserMessage","releaseNotePayload","m","v","key","assistantMessage","error","handleRegenerate","messageKey","messageIndex","msg","previousMessage","history","handleFollowupClick","question","emptyStateGreeting"],"mappings":";;;;;;;;;;;AAgBA,MAAMA,KAAmB,CAACC,MACxBA,KAAA,gBAAAA,EAAS,IAAI,CAACC,OAAY;AAAA,EACxB,MAAMA,EAAO,QAAQA,EAAO,OAAO;AAAA,EACnC,OAAOA,EAAO,SAAS;AACzB,KAEIC,KAAqB,CAACC,MAA+C;AACzE,MAAKA;AAIL,WAAI,OAAOA,KAAc,WAChB,EAAC,SAASA,GAAW,UAAU,EAAA,IAGjC;AAAA,MACL,SAASA,EAAU,WAAW;AAAA,MAC9B,UAAUA,EAAU,YAAY;AAAA,IAAA;AAEpC,GAEMC,IAA8B,CAACC,MAA6B;AAChE,MAAIA,EAAK,kBAAkB;AACzB,UAAM,IAAI,MAAM,2DAA2D;AAG7E,QAAMC,IAAK,aAAa,KAAK,IAAA,CAAK,IAC5BC,IAA2C;AAAA,IAC/C,IAAAD;AAAA,IACA,SAASD,EAAK,WAAW;AAAA,IACzB,cAAcA,EAAK;AAAA,IACnB,YAAYA,EAAK;AAAA,IACjB,mBAAmBA,EAAK;AAAA,EAAA;AAG1B,SAAO;AAAA,IACL,KAAKC;AAAA,IACL,SAAAC;AAAA,IACA,SAASR,GAAiBM,EAAK,OAAO;AAAA,IACtC,WAAWH,GAAmBG,EAAK,SAAS;AAAA,EAAA;AAEhD;AAEO,SAASG,KAAU;AACxB,QAAM,EAAC,OAAAC,EAAA,IAASC,EAAA,GACVC,IAAYC,GAAA,GACZ,EAAC,mBAAAC,GAAmB,qBAAAC,EAAA,IAAuBC,GAAA,GAE3C;AAAA,IACJ,MAAAC;AAAA,IACA,UAAAC;AAAA,EAAA,IACEC,GAAA,GAEE,CAACC,GAAcC,CAAe,IAAIC,EAAS,EAAK,GAChD,CAACC,GAAaC,CAAc,IAAIF,EAAS,EAAK,GAC9C,CAACG,GAAYC,CAAa,IAAIJ,EAAS,EAAE,GAEzC;AAAA,IACJ,cAAAK;AAAA,IACA,iBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,kBAAAC;AAAA,EAAA,IACEC,GAAA;AAEJ,EAAAC,GAAA,GACAC,GAAA,GACAC,GAAA;AAEA,QAAM;AAAA,IACJ,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,EAAA,IACEC,EAAA,GAEEC,IAAeC;AAAA,IACnB,OAAOC,MAAgC;;AAErC,UAAI,GAACC,IAAAD,EAAQ,SAAR,QAAAC,EAAc;AACjB;AAGF,YAAMC,IAAcF,EAAQ,KAAK,KAAA,GAC3BG,IAASC,EAAiBF,CAAW;AAE3C,UAAIG,EAAoBF,CAAM,GAAG;AAC/B,YAAIA,EAAO,YAAY,YAAY;AACjC,UAAAhC,EAAgB,EAAI;AACpB;AAAA,QACF;AAEA,YAAIgC,EAAO,YAAY,QAAQ;AAC7B,gBAAMG,IAA2B;AAAA,YAC/B,KAAK,aAAa,KAAK,IAAA,CAAK;AAAA,YAC5B,MAAM;AAAA,YACN,UAAU;AAAA,cACR;AAAA,gBACE,IAAI,aAAa,KAAK,IAAA,CAAK;AAAA,gBAC3B,SAASC,EAAA;AAAA,gBACT,cAAc;AAAA,cAAA;AAAA,YAChB;AAAA,YAEF,QAAQ;AAAA,YACR,MAAM;AAAA,UAAA;AAER,UAAA7B,EAAgB,CAAC8B,MAAS,CAAC,GAAGA,GAAMF,CAAW,CAAC,GAChD9B,EAAc,EAAE;AAChB;AAAA,QACF;AAEA,YAAI2B,EAAO,YAAY,SAAS;AAC9B,UAAAzB,EAAgB,CAAA,CAAE,GAClBlB,EAAM;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,UAAA,CACd,GACDgB,EAAc,EAAE;AAChB;AAAA,QACF;AAAA,MACF;AAEA,YAAMiC,IAA8B;AAAA,QAClC,KAAK,QAAQ,KAAK,IAAA,CAAK;AAAA,QACvB,MAAM;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,IAAI,QAAQ,KAAK,IAAA,CAAK;AAAA,YACtB,SAASP;AAAA,UAAA;AAAA,QACX;AAAA,QAEF,QAAQ;AAAA,QACR,MAAM;AAAA,MAAA;AAER,MAAAxB,EAAgB,CAAC8B,MAAS,CAAC,GAAGA,GAAMC,CAAc,CAAC,GACnDjC,EAAc,EAAE,GAEhB,WAAW,MAAM;AACf,QAAAS,EAAA;AAAA,MACF,GAAG,GAAG,GAENH,EAAoB,EAAI;AAExB,UAAI;AACF,cAAM4B,IAAqBlB,IACvB;AAAA,UACA,YAAYA,EAAoB;AAAA,UAChC,QAAQA,EAAoB;AAAA,UAC5B,SAASA,EAAoB;AAAA,QAAA,IAE7B,QAEEpC,IAAO,MAAMM,EAAU,WAAW;AAAA,UACtC,SAASwC;AAAA,UACT,qBAAqBzB,EAAa;AAAA,YAAQ,CAACkC,MACzCA,EAAE,SAAS,IAAI,CAACC,OAAwC;AAAA,cACtD,MAAMD,EAAE;AAAA,cACR,SAASC,EAAE;AAAA,YAAA,EACX;AAAA,UAAA;AAAA,UAEJ,YAAYrB,KAAc;AAAA,UAC1B,QAAQvB,KAAY;AAAA,UACpB,gBAAgBW,KAAyB;AAAA,UACzC,qBAAqB+B;AAAA,QAAA,CACtB;AAED,YAAItD,EAAK,kBAAkB,iBAAiB;AAC1C,UAAIA,EAAK,UAAU,yBACjBQ,EAAkB,EAAK,GAGzBc,EAAgB,CAAC8B,MAASA,EAAK,MAAM,GAAG,EAAE,CAAC,GAC3C3C,EAAoB;AAAA,YAClB,SAAST,EAAK,YAAY;AAAA,YAC1B,UAAUuB,KAAyB;AAAA,UAAA,CACpC,GAEDG,EAAoB,EAAK;AACzB;AAAA,QACF;AAEA,cAAM,EAAC,KAAA+B,GAAK,SAAAvD,GAAS,SAAAP,GAAS,WAAAG,EAAA,IAAaC,EAA4BC,CAAI,GAErE0D,IAAgC;AAAA,UACpC,KAAAD;AAAA,UACA,MAAM;AAAA,UACN,UAAU,CAACvD,CAAO;AAAA,UAClB,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,SAAAP;AAAA,UACA,WAAAG;AAAA,QAAA;AAGF,QAAAwB,EAAgB,CAAC8B,MAAS,CAAC,GAAGA,GAAMM,CAAgB,CAAC,GACrDhC,EAAoB,EAAK,GAEzB,WAAW,MAAM;AACf,UAAAG,EAAA;AAAA,QACF,GAAG,GAAG;AAAA,MACR,SAAS8B,GAAO;AACd,gBAAQ,MAAM,eAAeA,CAAK,GAClCjC,EAAoB,EAAK,GACzBtB,EAAM;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,QAAA,CACV;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,MACEE;AAAA,MACAe;AAAA,MACAE;AAAA,MACAX;AAAA,MACAuB;AAAA,MACAC;AAAA,MACAP;AAAA,MACApB;AAAA,MACAD;AAAA,MACAJ;AAAA,IAAA;AAAA,EACF,GAGIwD,IAAmBjB;AAAA,IACvB,OAAOkB,MAAuB;;AAC5B,YAAMC,IAAezC,EAAa,UAAU,CAAC0C,MAAQA,EAAI,QAAQF,CAAU;AAC3E,UAAIC,MAAiB,GAAI;AAEzB,YAAME,IAAkBF,IAAe,IAAIzC,EAAayC,IAAe,CAAC,IAAI,MACtEhB,MAAcD,IAAAmB,KAAA,gBAAAA,EAAiB,SAAS,OAA1B,gBAAAnB,EAA8B,YAAW;AAE7D,UAAI,CAACC,GAAa;AAChB,QAAA1C,EAAM;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,QAAA,CACV;AACD;AAAA,MACF;AAEA,MAAAsB,EAAoB,EAAI;AAExB,UAAI;AACF,cAAM4B,IAAqBlB,IACvB;AAAA,UACA,YAAYA,EAAoB;AAAA,UAChC,QAAQA,EAAoB;AAAA,UAC5B,SAASA,EAAoB;AAAA,QAAA,IAE7B,QAEE6B,IAAU5C,EAAa,MAAM,GAAGyC,CAAY,EAAE;AAAA,UAAQ,CAACP,MAC3DA,EAAE,SAAS,IAAI,CAACC,OAAwC;AAAA,YACtD,MAAMD,EAAE;AAAA,YACR,SAASC,EAAE;AAAA,UAAA,EACX;AAAA,QAAA,GAGExD,IAAO,MAAMM,EAAU,WAAW;AAAA,UACtC,SAASwC;AAAA,UACT,qBAAqBmB;AAAA,UACrB,YAAY9B,KAAc;AAAA,UAC1B,QAAQvB,KAAY;AAAA,UACpB,gBAAgBW,KAAyB;AAAA,UACzC,qBAAqB+B;AAAA,QAAA,CACtB;AAED,YAAItD,EAAK,kBAAkB,iBAAiB;AAC1C,UAAIA,EAAK,UAAU,yBACjBQ,EAAkB,EAAK,GAGzBC,EAAoB;AAAA,YAClB,SAAST,EAAK,YAAY;AAAA,YAC1B,UAAUuB,KAAyB;AAAA,UAAA,CACpC,GAEDG,EAAoB,EAAK;AACzB;AAAA,QACF;AAEA,cAAM,EAAC,SAAAxB,GAAS,SAAAP,GAAS,WAAAG,EAAA,IAAaC,EAA4BC,CAAI;AAEtE,QAAAsB;AAAA,UAAgB,CAAC8B,MACfA,EAAK,IAAI,CAACW,MACJA,EAAI,QAAQF,IACP;AAAA,YACL,GAAGE;AAAA,YACH,UAAU,CAAC,GAAGA,EAAI,UAAU7D,CAAO;AAAA,YACnC,SAAAP;AAAA,YACA,WAAAG;AAAA,UAAA,IAGGiE,CACR;AAAA,QAAA,GAGHrC,EAAoB,EAAK,GACzB,WAAW,MAAM;AACf,UAAAG,EAAA;AAAA,QACF,GAAG,GAAG;AAAA,MACR,SAAS8B,GAAO;AACd,gBAAQ,MAAM,qBAAqBA,CAAK,GACxCjC,EAAoB,EAAK,GACzBtB,EAAM;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,QAAA,CACV;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,MACEE;AAAA,MACAe;AAAA,MACAE;AAAA,MACAX;AAAA,MACAuB;AAAA,MACAC;AAAA,MACAP;AAAA,MACArB;AAAA,MACAJ;AAAA,IAAA;AAAA,EACF,GAGI8D,IAAsBvB,EAAY,CAACwB,MAAqB;AAC5D,IAAA/C,EAAc+C,CAAQ;AAAA,EACxB,GAAG,CAAA,CAAE,GAECC,IAAqBzD,KAAA,QAAAA,EAAM,WAC7B,WAAWA,EAAK,SAAS,MAAM,GAAG,EAAE,CAAC,CAAC,QACtC;AAEJ,SAAO;AAAA,IACL,cAAAU;AAAA,IACA,cAAAP;AAAA,IACA,iBAAAC;AAAA,IACA,aAAAE;AAAA,IACA,gBAAAC;AAAA,IACA,uBAAAM;AAAA,IACA,uBAAAD;AAAA,IACA,kBAAAI;AAAA,IACA,uBAAAC;AAAA,IACA,kBAAAH;AAAA,IACA,YAAAS;AAAA,IACA,cAAAG;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,qBAAA0B;AAAA,IACA,cAAAxB;AAAA,IACA,kBAAAkB;AAAA,IACA,YAAAzC;AAAA,IACA,eAAAC;AAAA,IACA,oBAAAgD;AAAA,EAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"useChat.js","sources":["../../../../lib/organisms/chat/hooks/useChat.ts"],"sourcesContent":["\"use client\";\n\nimport {useCallback, useState} from \"react\";\nimport {getCommandHelp, parseChatCommand, shouldHandleCommand} from \"../../../utils/chat-commands\";\nimport {useToast} from \"../../../molecules/Notifications/useToast\";\nimport type {PromptInputMessage} from \"@clubmed/usg-chat-ui/molecules/AiElements/PromptInput\";\nimport {useCanvasStore} from \"../../../utils/canvas-store\";\nimport type {ChatMessage} from \"../types\";\nimport type {ChatCanvasResponse} from \"@clubmed/usg-chat-ui/core/interfaces/ChatCanvas\";\nimport {useChatApiClient, useChatConfig} from \"../../../contexts/ChatContext\";\nimport {useConversations} from \"./useConversations\";\nimport {useChatJira} from \"@clubmed/usg-chat-ui/contexts/ChatJiraContext\";\nimport {useChatPreferences} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences\";\nimport {useChatSyncUserSettings} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings\";\nimport {useChatKeyboardsShortcuts} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts\";\n\nconst mapCanvasSources = (sources: ChatCanvasResponse[\"sources\"]) =>\n sources?.map((source) => ({\n href: source.href || source.url || \"#\",\n title: source.title || \"Source\",\n }));\n\nconst mapCanvasReasoning = (reasoning: ChatCanvasResponse[\"reasoning\"]) => {\n if (!reasoning) {\n return undefined;\n }\n\n if (typeof reasoning === \"string\") {\n return {content: reasoning, duration: 0};\n }\n\n return {\n content: reasoning.content ?? \"\",\n duration: reasoning.duration ?? 0,\n };\n};\n\nconst buildAssistantResponseParts = (data: ChatCanvasResponse) => {\n if (data.response_type === \"auth_required\") {\n throw new Error(\"Cannot build assistant response for auth-required payload\");\n }\n\n const id = `assistant-${Date.now()}`;\n const version: ChatMessage[\"versions\"][number] = {\n id,\n content: data.content || \"Aucune réponse disponible\",\n responseType: data.response_type,\n canvasData: data.canvas_data,\n followupQuestions: data.followup_questions,\n };\n\n return {\n key: id,\n version,\n sources: mapCanvasSources(data.sources),\n reasoning: mapCanvasReasoning(data.reasoning),\n };\n};\n\nexport function useChat() {\n const {toast} = useToast();\n const apiClient = useChatApiClient();\n const {setJiraConfigured, setJiraAuthSettings} = useChatJira();\n\n const {\n user,\n dbUserId,\n } = useChatConfig();\n\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [localInput, setLocalInput] = useState(\"\");\n\n const {\n chatMessages,\n setChatMessages,\n currentConversationId,\n sidebarRefreshTrigger,\n isLoadingMessage,\n setIsLoadingMessage,\n loadConversation,\n handleNewConversation,\n saveConversation,\n } = useConversations();\n\n useChatSyncUserSettings();\n useChatKeyboardsShortcuts();\n useChatPreferences();\n\n const {\n canvasType,\n projectKey,\n releaseNoteSettings,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n } = useCanvasStore();\n\n const handleSubmit = useCallback(\n async (message: PromptInputMessage) => {\n\n if (!message.text?.trim()) {\n return;\n }\n\n const userMessage = message.text.trim();\n const parsed = parseChatCommand(userMessage);\n\n if (shouldHandleCommand(parsed)) {\n if (parsed.command === \"settings\") {\n setSettingsOpen(true);\n return;\n }\n\n if (parsed.command === \"help\") {\n const helpMessage: ChatMessage = {\n key: `assistant-${Date.now()}`,\n from: \"assistant\",\n versions: [\n {\n id: `assistant-${Date.now()}`,\n content: getCommandHelp(),\n responseType: \"message\",\n },\n ],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n };\n setChatMessages((prev) => [...prev, helpMessage]);\n setLocalInput(\"\");\n return;\n }\n\n if (parsed.command === \"clear\") {\n setChatMessages([]);\n toast({\n title: \"Cleared\",\n description: \"Conversation history cleared\",\n });\n setLocalInput(\"\");\n return;\n }\n }\n\n const newUserMessage: ChatMessage = {\n key: `user-${Date.now()}`,\n from: \"user\",\n versions: [\n {\n id: `user-${Date.now()}`,\n content: userMessage,\n },\n ],\n avatar: \"https://github.com/haydenbleasel.png\",\n name: \"User\",\n };\n setChatMessages((prev) => [...prev, newUserMessage]);\n setLocalInput(\"\");\n\n setTimeout(() => {\n saveConversation();\n }, 200);\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: chatMessages.flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n ),\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setChatMessages((prev) => prev.slice(0, -1));\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {key, version, sources, reasoning} = buildAssistantResponseParts(data);\n\n const assistantMessage: ChatMessage = {\n key,\n from: \"assistant\",\n versions: [version],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n sources,\n reasoning,\n };\n\n setChatMessages((prev) => [...prev, assistantMessage]);\n setIsLoadingMessage(false);\n\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Chat error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Error\",\n description: \"Failed to get response. Please try again.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraAuthSettings,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleRegenerate = useCallback(\n async (messageKey: string) => {\n const messageIndex = chatMessages.findIndex((msg) => msg.key === messageKey);\n if (messageIndex === -1) return;\n\n const previousMessage = messageIndex > 0 ? chatMessages[messageIndex - 1] : null;\n const userMessage = previousMessage?.versions[0]?.content || \"\";\n\n if (!userMessage) {\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer : aucun message précédent trouvé\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const history = chatMessages.slice(0, messageIndex).flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n );\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: history,\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {version, sources, reasoning} = buildAssistantResponseParts(data);\n\n setChatMessages((prev) =>\n prev.map((msg) => {\n if (msg.key === messageKey) {\n return {\n ...msg,\n versions: [...msg.versions, version],\n sources,\n reasoning,\n };\n }\n return msg;\n })\n );\n\n setIsLoadingMessage(false);\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Regenerate error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer la réponse. Veuillez réessayer.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleFollowupClick = useCallback((question: string) => {\n setLocalInput(question);\n }, []);\n\n const emptyStateGreeting = user?.userName\n ? `Bonjour ${user.userName.split(\" \")[0]} 👋`\n : undefined;\n\n return {\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n emptyStateGreeting\n };\n}\n"],"names":["mapCanvasSources","sources","source","mapCanvasReasoning","reasoning","buildAssistantResponseParts","data","id","version","useChat","toast","useToast","apiClient","useChatApiClient","setJiraConfigured","setJiraAuthSettings","useChatJira","user","dbUserId","useChatConfig","settingsOpen","setSettingsOpen","useState","sidebarOpen","setSidebarOpen","localInput","setLocalInput","chatMessages","setChatMessages","currentConversationId","sidebarRefreshTrigger","isLoadingMessage","setIsLoadingMessage","loadConversation","handleNewConversation","saveConversation","useConversations","useChatSyncUserSettings","useChatKeyboardsShortcuts","useChatPreferences","canvasType","projectKey","releaseNoteSettings","isFullscreen","canvasWidth","isResizing","resizeWidth","useCanvasStore","handleSubmit","useCallback","message","_a","userMessage","parsed","parseChatCommand","shouldHandleCommand","helpMessage","getCommandHelp","prev","newUserMessage","releaseNotePayload","m","v","key","assistantMessage","error","handleRegenerate","messageKey","messageIndex","msg","previousMessage","history","handleFollowupClick","question","emptyStateGreeting"],"mappings":"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"}
|