@agent-native/toolkit 0.216.0 → 0.218.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +26 -0
- package/dist/app/agent-page/AgentContextTab.d.ts.map +1 -1
- package/dist/app/agent-page/AgentContextTab.js +1 -0
- package/dist/app/agent-page/AgentContextTab.js.map +1 -1
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +1 -1
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +4 -1
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +3 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/data-chart-layout.d.ts +30 -0
- package/dist/app/agentkit/react/data-chart-layout.d.ts.map +1 -0
- package/dist/app/agentkit/react/data-chart-layout.js +2 -0
- package/dist/app/agentkit/react/data-chart-layout.js.map +1 -0
- package/dist/app/agentkit/react/index.d.ts +1 -0
- package/dist/app/agentkit/react/index.d.ts.map +1 -1
- package/dist/app/agentkit/react/index.js +1 -0
- package/dist/app/agentkit/react/index.js.map +1 -1
- package/dist/app/agentkit/react/root.d.ts +3 -1
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +18 -0
- package/dist/app/agentkit/react/transcript-layout.d.ts +2 -0
- package/dist/app/agentkit/react/transcript-layout.d.ts.map +1 -1
- package/dist/app/agentkit/react/transcript-layout.js.map +1 -1
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +33 -44
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +2 -2
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +51 -93
- package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/action-widget.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/action-widget.js +3 -1
- package/dist/app/chat/agentkit-chat/action-widget.js.map +1 -1
- package/dist/app/chat/agentkit-chat/rail.d.ts +1 -1
- package/dist/app/chat/agentkit-chat/rail.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/rail.js +1 -1
- package/dist/app/chat/agentkit-chat/rail.js.map +1 -1
- package/dist/app/chat/chat/index.d.ts +2 -1
- package/dist/app/chat/chat/index.d.ts.map +1 -1
- package/dist/app/chat/chat/index.js +1 -1
- package/dist/app/chat/chat/index.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +3 -0
- package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
- package/dist/app/chat/chat/surface-types.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts +3 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +4 -3
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/chat/tool-render-registry.d.ts +2 -0
- package/dist/app/chat/chat/tool-render-registry.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-render-registry.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts +3 -1
- package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartRenderer.js +116 -26
- package/dist/app/chat/chat/widgets/DataChartRenderer.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartWidget.d.ts +3 -1
- package/dist/app/chat/chat/widgets/DataChartWidget.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartWidget.js +21 -2
- package/dist/app/chat/chat/widgets/DataChartWidget.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataInsightsWidget.d.ts +3 -1
- package/dist/app/chat/chat/widgets/DataInsightsWidget.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataInsightsWidget.js +2 -2
- package/dist/app/chat/chat/widgets/DataInsightsWidget.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts +1 -1
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js +3 -1
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js.map +1 -1
- package/dist/app/chat/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/builtin-tool-renderers.js +2 -2
- package/dist/app/chat/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/app/chat/chat-first/chat-history.d.ts +13 -2
- package/dist/app/chat/chat-first/chat-history.d.ts.map +1 -1
- package/dist/app/chat/chat-first/chat-history.js +24 -3
- package/dist/app/chat/chat-first/chat-history.js.map +1 -1
- package/dist/app/chat/ownership-history/ChatOwnerAvatar.d.ts +6 -0
- package/dist/app/chat/ownership-history/ChatOwnerAvatar.d.ts.map +1 -0
- package/dist/app/chat/ownership-history/ChatOwnerAvatar.js +9 -0
- package/dist/app/chat/ownership-history/ChatOwnerAvatar.js.map +1 -0
- package/dist/app/chat/ownership-history/index.d.ts +11 -0
- package/dist/app/chat/ownership-history/index.d.ts.map +1 -0
- package/dist/app/chat/ownership-history/index.js +22 -0
- package/dist/app/chat/ownership-history/index.js.map +1 -0
- package/dist/app/chat/ownership-history/rows.d.ts +27 -0
- package/dist/app/chat/ownership-history/rows.d.ts.map +1 -0
- package/dist/app/chat/ownership-history/rows.js +101 -0
- package/dist/app/chat/ownership-history/rows.js.map +1 -0
- package/dist/app/chat/ownership-history/useOwnershipChatHistory.d.ts +52 -0
- package/dist/app/chat/ownership-history/useOwnershipChatHistory.d.ts.map +1 -0
- package/dist/app/chat/ownership-history/useOwnershipChatHistory.js +497 -0
- package/dist/app/chat/ownership-history/useOwnershipChatHistory.js.map +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +3 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +3 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +3 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +3 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +3 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +3 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +3 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +3 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +3 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +3 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +3 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +3 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/GettingStartedCard.d.ts +35 -0
- package/dist/app/onboarding/GettingStartedCard.d.ts.map +1 -0
- package/dist/app/onboarding/GettingStartedCard.js +38 -0
- package/dist/app/onboarding/GettingStartedCard.js.map +1 -0
- package/dist/app/onboarding/index.d.ts +1 -0
- package/dist/app/onboarding/index.d.ts.map +1 -1
- package/dist/app/onboarding/index.js +1 -0
- package/dist/app/onboarding/index.js.map +1 -1
- package/dist/app/providers/AppProviders.d.ts.map +1 -1
- package/dist/app/providers/AppProviders.js +3 -1
- package/dist/app/providers/AppProviders.js.map +1 -1
- package/dist/app/settings/AccountSettingsCard.d.ts.map +1 -1
- package/dist/app/settings/AccountSettingsCard.js +2 -1
- package/dist/app/settings/AccountSettingsCard.js.map +1 -1
- package/dist/app/settings/index.d.ts +1 -0
- package/dist/app/settings/index.d.ts.map +1 -1
- package/dist/app/settings/index.js +1 -0
- package/dist/app/settings/index.js.map +1 -1
- package/dist/app/settings/shell/SettingsShell.d.ts +40 -1
- package/dist/app/settings/shell/SettingsShell.d.ts.map +1 -1
- package/dist/app/settings/shell/SettingsShell.js +87 -20
- package/dist/app/settings/shell/SettingsShell.js.map +1 -1
- package/dist/app/settings/shell/bridge.d.ts +5 -3
- package/dist/app/settings/shell/bridge.d.ts.map +1 -1
- package/dist/app/settings/shell/bridge.js +8 -5
- package/dist/app/settings/shell/bridge.js.map +1 -1
- package/dist/app/settings/shell/index.d.ts +2 -2
- package/dist/app/settings/shell/index.d.ts.map +1 -1
- package/dist/app/settings/shell/index.js.map +1 -1
- package/dist/app/settings/shell/registry.d.ts +9 -1
- package/dist/app/settings/shell/registry.d.ts.map +1 -1
- package/dist/app/settings/shell/registry.js +16 -0
- package/dist/app/settings/shell/registry.js.map +1 -1
- package/dist/app/settings/shell/routing.d.ts +5 -4
- package/dist/app/settings/shell/routing.d.ts.map +1 -1
- package/dist/app/settings/shell/routing.js +38 -10
- package/dist/app/settings/shell/routing.js.map +1 -1
- package/dist/app/shared/CommandMenu.d.ts +86 -6
- package/dist/app/shared/CommandMenu.d.ts.map +1 -1
- package/dist/app/shared/CommandMenu.js +303 -41
- package/dist/app/shared/CommandMenu.js.map +1 -1
- package/dist/app/shared/ConsentBanner.d.ts +9 -0
- package/dist/app/shared/ConsentBanner.d.ts.map +1 -0
- package/dist/app/shared/ConsentBanner.js +35 -0
- package/dist/app/shared/ConsentBanner.js.map +1 -0
- package/dist/app/sharing/ShareButton.d.ts.map +1 -1
- package/dist/app/sharing/ShareButton.js +9 -8
- package/dist/app/sharing/ShareButton.js.map +1 -1
- package/dist/chat-history/ChatHistoryList.d.ts +16 -3
- package/dist/chat-history/ChatHistoryList.d.ts.map +1 -1
- package/dist/chat-history/ChatHistoryList.js +25 -15
- package/dist/chat-history/ChatHistoryList.js.map +1 -1
- package/dist/chat-history.css +109 -9
- package/dist/ui/sonner.d.ts +2 -2
- package/dist/ui/sonner.d.ts.map +1 -1
- package/dist/ui/sonner.js +2 -2
- package/dist/ui/sonner.js.map +1 -1
- package/package.json +10 -3
- package/src/app/agent-page/AgentContextTab.spec.ts +50 -2
- package/src/app/agent-page/AgentContextTab.tsx +1 -0
- package/src/app/agentkit/react/components.interaction.spec.tsx +2 -0
- package/src/app/agentkit/react/components.spec.tsx +4 -1
- package/src/app/agentkit/react/components.tsx +3 -0
- package/src/app/agentkit/react/context.tsx +6 -0
- package/src/app/agentkit/react/data-chart-layout.ts +25 -0
- package/src/app/agentkit/react/index.ts +1 -0
- package/src/app/agentkit/react/root.tsx +4 -0
- package/src/app/agentkit/react/styles.css +18 -0
- package/src/app/agentkit/react/transcript-layout.ts +2 -0
- package/src/app/auth/AuthPage.interaction.spec.tsx +74 -0
- package/src/app/auth/AuthPage.tsx +32 -39
- package/src/app/chat/AgentKitAssistantChat.tsx +2 -0
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +270 -3
- package/src/app/chat/MultiTabAssistantChat.tsx +79 -156
- package/src/app/chat/agentkit-chat/action-widget.tsx +3 -0
- package/src/app/chat/agentkit-chat/rail.ts +11 -0
- package/src/app/chat/chat/index.ts +10 -0
- package/src/app/chat/chat/surface-types.ts +3 -0
- package/src/app/chat/chat/tool-call-display.spec.tsx +29 -0
- package/src/app/chat/chat/tool-call-display.tsx +7 -0
- package/src/app/chat/chat/tool-render-registry.tsx +3 -0
- package/src/app/chat/chat/widgets/DataChartRenderer.spec.tsx +377 -17
- package/src/app/chat/chat/widgets/DataChartRenderer.tsx +232 -63
- package/src/app/chat/chat/widgets/DataChartWidget.spec.tsx +67 -0
- package/src/app/chat/chat/widgets/DataChartWidget.tsx +39 -5
- package/src/app/chat/chat/widgets/DataInsightsWidget.tsx +13 -2
- package/src/app/chat/chat/widgets/DataWidgetDisplayControls.tsx +6 -4
- package/src/app/chat/chat/widgets/builtin-tool-renderers.tsx +5 -1
- package/src/app/chat/chat-first/chat-history.spec.tsx +79 -0
- package/src/app/chat/chat-first/chat-history.tsx +75 -22
- package/src/app/chat/ownership-history/ChatOwnerAvatar.tsx +27 -0
- package/src/app/chat/ownership-history/index.tsx +67 -0
- package/src/app/chat/ownership-history/ownership-history.spec.tsx +3146 -0
- package/src/app/chat/ownership-history/rows.ts +156 -0
- package/src/app/chat/ownership-history/useOwnershipChatHistory.ts +709 -0
- package/src/app/i18n/catalogs/ar-SA.ts +3 -0
- package/src/app/i18n/catalogs/de-DE.ts +3 -0
- package/src/app/i18n/catalogs/en-US.ts +3 -0
- package/src/app/i18n/catalogs/es-ES.ts +3 -0
- package/src/app/i18n/catalogs/fr-FR.ts +3 -0
- package/src/app/i18n/catalogs/hi-IN.ts +3 -0
- package/src/app/i18n/catalogs/ja-JP.ts +3 -0
- package/src/app/i18n/catalogs/ko-KR.ts +3 -0
- package/src/app/i18n/catalogs/pt-BR.ts +3 -0
- package/src/app/i18n/catalogs/zh-CN.ts +3 -0
- package/src/app/i18n/catalogs/zh-TW.ts +3 -0
- package/src/app/onboarding/GettingStartedCard.tsx +203 -0
- package/src/app/onboarding/index.ts +1 -0
- package/src/app/providers/AppProviders.tsx +7 -1
- package/src/app/settings/AccountSettingsCard.spec.tsx +31 -0
- package/src/app/settings/AccountSettingsCard.tsx +8 -0
- package/src/app/settings/index.ts +1 -0
- package/src/app/settings/shell/SettingsShell.spec.tsx +472 -1
- package/src/app/settings/shell/SettingsShell.tsx +245 -31
- package/src/app/settings/shell/bridge.spec.ts +12 -0
- package/src/app/settings/shell/bridge.ts +17 -4
- package/src/app/settings/shell/index.ts +6 -1
- package/src/app/settings/shell/registry.ts +33 -1
- package/src/app/settings/shell/routing.spec.ts +92 -1
- package/src/app/settings/shell/routing.ts +52 -9
- package/src/app/shared/CommandMenu.spec.tsx +1662 -1
- package/src/app/shared/CommandMenu.tsx +763 -164
- package/src/app/shared/ConsentBanner.spec.tsx +141 -0
- package/src/app/shared/ConsentBanner.tsx +141 -0
- package/src/app/sharing/ShareButton.tsx +12 -10
- package/src/chat-history/ChatHistoryList.spec.tsx +51 -0
- package/src/chat-history/ChatHistoryList.tsx +87 -26
- package/src/chat-history/ChatHistoryRailSections.spec.tsx +12 -4
- package/src/chat-history.css +109 -9
- package/src/ui/sonner.spec.ts +10 -0
- package/src/ui/sonner.tsx +2 -2
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { act } from "react";
|
|
4
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
const consentStateKey = Symbol.for("agent-native.client.consent");
|
|
8
|
+
|
|
9
|
+
let root: Root | null = null;
|
|
10
|
+
let container: HTMLElement | null = null;
|
|
11
|
+
|
|
12
|
+
async function renderBanner(region: "consent" | "none") {
|
|
13
|
+
vi.stubGlobal(
|
|
14
|
+
"fetch",
|
|
15
|
+
vi.fn(async () => new Response(JSON.stringify({ region }))),
|
|
16
|
+
);
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
const consent = await import("@agent-native/core/client/consent");
|
|
19
|
+
const { ConsentBanner } = await import("./ConsentBanner.js");
|
|
20
|
+
container = document.createElement("div");
|
|
21
|
+
document.body.appendChild(container);
|
|
22
|
+
root = createRoot(container);
|
|
23
|
+
await act(async () => {
|
|
24
|
+
root!.render(<ConsentBanner />);
|
|
25
|
+
});
|
|
26
|
+
await act(async () => {
|
|
27
|
+
await consent.resolveConsentRegion();
|
|
28
|
+
});
|
|
29
|
+
return consent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function banner() {
|
|
33
|
+
return document.querySelector("[data-agent-native-consent-banner]");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function button(name: string) {
|
|
37
|
+
const match = [...document.querySelectorAll("button")].find(
|
|
38
|
+
(el) => el.textContent === name,
|
|
39
|
+
);
|
|
40
|
+
if (!match) throw new Error(`no ${name} button`);
|
|
41
|
+
return match;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function click(name: string) {
|
|
45
|
+
await act(async () => {
|
|
46
|
+
button(name).click();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe("ConsentBanner", () => {
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
act(() => root?.unmount());
|
|
53
|
+
container?.remove();
|
|
54
|
+
root = null;
|
|
55
|
+
delete (globalThis as any)[consentStateKey];
|
|
56
|
+
window.sessionStorage.clear();
|
|
57
|
+
for (const cookie of document.cookie.split(";")) {
|
|
58
|
+
const name = cookie.split("=")[0]?.trim();
|
|
59
|
+
if (name) document.cookie = `${name}=; path=/; max-age=0`;
|
|
60
|
+
}
|
|
61
|
+
vi.unstubAllGlobals();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("shows nothing outside the consent region", async () => {
|
|
65
|
+
await renderBanner("none");
|
|
66
|
+
expect(banner()).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("shows on a later page once the region is already known this session", async () => {
|
|
70
|
+
window.sessionStorage.setItem("an_consent_region", "consent");
|
|
71
|
+
const fetchMock = vi.fn(async () => new Response("{}"));
|
|
72
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
73
|
+
vi.resetModules();
|
|
74
|
+
const { ConsentBanner } = await import("./ConsentBanner.js");
|
|
75
|
+
container = document.createElement("div");
|
|
76
|
+
document.body.appendChild(container);
|
|
77
|
+
root = createRoot(container);
|
|
78
|
+
await act(async () => {
|
|
79
|
+
root!.render(<ConsentBanner />);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(banner()).not.toBeNull();
|
|
83
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("stores accept-all and closes", async () => {
|
|
87
|
+
const consent = await renderBanner("consent");
|
|
88
|
+
expect(banner()).not.toBeNull();
|
|
89
|
+
|
|
90
|
+
await click("Accept all");
|
|
91
|
+
|
|
92
|
+
expect(consent.getConsentChoice()).toEqual({
|
|
93
|
+
performance: true,
|
|
94
|
+
targeting: true,
|
|
95
|
+
});
|
|
96
|
+
expect(banner()).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("stores reject-all and closes", async () => {
|
|
100
|
+
const consent = await renderBanner("consent");
|
|
101
|
+
|
|
102
|
+
await click("Reject all");
|
|
103
|
+
|
|
104
|
+
expect(consent.getConsentChoice()).toEqual({
|
|
105
|
+
performance: false,
|
|
106
|
+
targeting: false,
|
|
107
|
+
});
|
|
108
|
+
expect(banner()).toBeNull();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("saves one category from the settings", async () => {
|
|
112
|
+
const consent = await renderBanner("consent");
|
|
113
|
+
|
|
114
|
+
await click("Manage settings");
|
|
115
|
+
await act(async () => {
|
|
116
|
+
(
|
|
117
|
+
document.getElementById("an-consent-performance") as HTMLElement
|
|
118
|
+
).click();
|
|
119
|
+
});
|
|
120
|
+
await click("Save choices");
|
|
121
|
+
|
|
122
|
+
expect(consent.getConsentChoice()).toEqual({
|
|
123
|
+
performance: true,
|
|
124
|
+
targeting: false,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("reopens from the settings link with the stored choice", async () => {
|
|
129
|
+
const consent = await renderBanner("consent");
|
|
130
|
+
await click("Accept all");
|
|
131
|
+
|
|
132
|
+
await act(async () => consent.openConsentSettings());
|
|
133
|
+
await click("Manage settings");
|
|
134
|
+
|
|
135
|
+
expect(
|
|
136
|
+
document
|
|
137
|
+
.getElementById("an-consent-targeting")
|
|
138
|
+
?.getAttribute("aria-checked"),
|
|
139
|
+
).toBe("true");
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getConsentChoice,
|
|
3
|
+
resolveConsentRegion,
|
|
4
|
+
setConsentChoice,
|
|
5
|
+
shouldShowConsentBanner,
|
|
6
|
+
subscribeConsent,
|
|
7
|
+
} from "@agent-native/core/client/consent";
|
|
8
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
9
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
10
|
+
import { Label } from "@agent-native/toolkit/ui/label";
|
|
11
|
+
import { Switch } from "@agent-native/toolkit/ui/switch";
|
|
12
|
+
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
13
|
+
|
|
14
|
+
const DEFAULT_PRIVACY_POLICY_HREF = "https://www.agent-native.com/privacy";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The cookie banner for visitors in the consent region. Renders nothing
|
|
18
|
+
* elsewhere, and nothing once the visitor has chosen, until
|
|
19
|
+
* `openConsentSettings()` reopens it.
|
|
20
|
+
*/
|
|
21
|
+
export function ConsentBanner({
|
|
22
|
+
privacyPolicyHref = DEFAULT_PRIVACY_POLICY_HREF,
|
|
23
|
+
}: {
|
|
24
|
+
privacyPolicyHref?: string;
|
|
25
|
+
}) {
|
|
26
|
+
const t = useT();
|
|
27
|
+
const open = useSyncExternalStore(
|
|
28
|
+
subscribeConsent,
|
|
29
|
+
shouldShowConsentBanner,
|
|
30
|
+
() => false,
|
|
31
|
+
);
|
|
32
|
+
const [managing, setManaging] = useState(false);
|
|
33
|
+
const [performance, setPerformance] = useState(false);
|
|
34
|
+
const [targeting, setTargeting] = useState(false);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
void resolveConsentRegion();
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!open) return;
|
|
42
|
+
const stored = getConsentChoice();
|
|
43
|
+
setPerformance(stored?.performance ?? false);
|
|
44
|
+
setTargeting(stored?.targeting ?? false);
|
|
45
|
+
setManaging(false);
|
|
46
|
+
}, [open]);
|
|
47
|
+
|
|
48
|
+
if (!open) return null;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<section
|
|
52
|
+
role="region"
|
|
53
|
+
aria-label={t("consentBanner.label")}
|
|
54
|
+
data-agent-native-consent-banner
|
|
55
|
+
className="fixed bottom-4 left-4 z-[100] flex w-[min(420px,calc(100vw-2rem))] flex-col gap-3 rounded-lg border bg-popover p-4 text-sm text-popover-foreground shadow-lg"
|
|
56
|
+
>
|
|
57
|
+
<p className="m-0 leading-relaxed">
|
|
58
|
+
{t("consentBanner.message")}{" "}
|
|
59
|
+
<a
|
|
60
|
+
href={privacyPolicyHref}
|
|
61
|
+
target="_blank"
|
|
62
|
+
rel="noreferrer"
|
|
63
|
+
className="underline underline-offset-2"
|
|
64
|
+
>
|
|
65
|
+
{t("consentBanner.privacyPolicy")}
|
|
66
|
+
</a>
|
|
67
|
+
</p>
|
|
68
|
+
{managing ? (
|
|
69
|
+
<div className="flex flex-col gap-2">
|
|
70
|
+
<div className="flex items-center justify-between gap-3">
|
|
71
|
+
<Label htmlFor="an-consent-necessary">
|
|
72
|
+
{t("consentBanner.necessary")}
|
|
73
|
+
</Label>
|
|
74
|
+
<Switch id="an-consent-necessary" checked disabled />
|
|
75
|
+
</div>
|
|
76
|
+
<div className="flex items-center justify-between gap-3">
|
|
77
|
+
<Label htmlFor="an-consent-performance">
|
|
78
|
+
{t("consentBanner.performance")}
|
|
79
|
+
</Label>
|
|
80
|
+
<Switch
|
|
81
|
+
id="an-consent-performance"
|
|
82
|
+
checked={performance}
|
|
83
|
+
onCheckedChange={setPerformance}
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
<div className="flex items-center justify-between gap-3">
|
|
87
|
+
<Label htmlFor="an-consent-targeting">
|
|
88
|
+
{t("consentBanner.targeting")}
|
|
89
|
+
</Label>
|
|
90
|
+
<Switch
|
|
91
|
+
id="an-consent-targeting"
|
|
92
|
+
checked={targeting}
|
|
93
|
+
onCheckedChange={setTargeting}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
) : null}
|
|
98
|
+
<div className="flex flex-wrap gap-2">
|
|
99
|
+
<Button
|
|
100
|
+
variant="outline"
|
|
101
|
+
size="sm"
|
|
102
|
+
className="flex-1"
|
|
103
|
+
onClick={() =>
|
|
104
|
+
setConsentChoice({ performance: false, targeting: false })
|
|
105
|
+
}
|
|
106
|
+
>
|
|
107
|
+
{t("consentBanner.rejectAll")}
|
|
108
|
+
</Button>
|
|
109
|
+
<Button
|
|
110
|
+
variant="outline"
|
|
111
|
+
size="sm"
|
|
112
|
+
className="flex-1"
|
|
113
|
+
onClick={() =>
|
|
114
|
+
setConsentChoice({ performance: true, targeting: true })
|
|
115
|
+
}
|
|
116
|
+
>
|
|
117
|
+
{t("consentBanner.acceptAll")}
|
|
118
|
+
</Button>
|
|
119
|
+
{managing ? (
|
|
120
|
+
<Button
|
|
121
|
+
variant="outline"
|
|
122
|
+
size="sm"
|
|
123
|
+
className="flex-1"
|
|
124
|
+
onClick={() => setConsentChoice({ performance, targeting })}
|
|
125
|
+
>
|
|
126
|
+
{t("consentBanner.save")}
|
|
127
|
+
</Button>
|
|
128
|
+
) : (
|
|
129
|
+
<Button
|
|
130
|
+
variant="ghost"
|
|
131
|
+
size="sm"
|
|
132
|
+
className="flex-1"
|
|
133
|
+
onClick={() => setManaging(true)}
|
|
134
|
+
>
|
|
135
|
+
{t("consentBanner.manage")}
|
|
136
|
+
</Button>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
</section>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
@@ -1150,6 +1150,12 @@ function MemberAutocomplete({
|
|
|
1150
1150
|
activeIndex >= 0 && activeIndex < suggestions.length
|
|
1151
1151
|
? suggestions[activeIndex]
|
|
1152
1152
|
: null;
|
|
1153
|
+
const listOpen =
|
|
1154
|
+
open &&
|
|
1155
|
+
(suggestions.length > 0 ||
|
|
1156
|
+
search.isLoading ||
|
|
1157
|
+
Boolean(search.error) ||
|
|
1158
|
+
value.trim().length > 0);
|
|
1153
1159
|
|
|
1154
1160
|
useEffect(() => {
|
|
1155
1161
|
setActiveIndex(-1);
|
|
@@ -1230,7 +1236,7 @@ function MemberAutocomplete({
|
|
|
1230
1236
|
};
|
|
1231
1237
|
|
|
1232
1238
|
return (
|
|
1233
|
-
<Popover open={
|
|
1239
|
+
<Popover open={listOpen} onOpenChange={onOpenChange}>
|
|
1234
1240
|
<PopoverAnchor asChild>
|
|
1235
1241
|
<div className="flex h-9 min-w-0 flex-1 items-center overflow-hidden rounded-md border border-input bg-card focus-within:ring-1 focus-within:ring-ring">
|
|
1236
1242
|
<input
|
|
@@ -1238,8 +1244,8 @@ function MemberAutocomplete({
|
|
|
1238
1244
|
type="text"
|
|
1239
1245
|
role="combobox"
|
|
1240
1246
|
aria-autocomplete="list"
|
|
1241
|
-
aria-expanded={
|
|
1242
|
-
aria-controls={
|
|
1247
|
+
aria-expanded={listOpen}
|
|
1248
|
+
aria-controls={listOpen ? listboxId : undefined}
|
|
1243
1249
|
aria-activedescendant={
|
|
1244
1250
|
activeIndex >= 0 ? optionId(listboxId, activeIndex) : undefined
|
|
1245
1251
|
}
|
|
@@ -1361,13 +1367,9 @@ function MemberAutocomplete({
|
|
|
1361
1367
|
|
|
1362
1368
|
{!search.isLoading && !search.error && suggestions.length === 0 ? (
|
|
1363
1369
|
<div className="px-3 py-3 text-sm text-muted-foreground">
|
|
1364
|
-
{
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
})
|
|
1368
|
-
: t("agentChat.share.noPeopleFound", {
|
|
1369
|
-
defaultValue: "No people found.",
|
|
1370
|
-
})}
|
|
1370
|
+
{t("agentChat.share.noMatches", {
|
|
1371
|
+
defaultValue: "No matches.",
|
|
1372
|
+
})}
|
|
1371
1373
|
</div>
|
|
1372
1374
|
) : null}
|
|
1373
1375
|
|
|
@@ -635,4 +635,55 @@ describe("ChatHistoryList", () => {
|
|
|
635
635
|
});
|
|
636
636
|
expect(container.querySelector(".an-chat-history-row__menu")).toBeNull();
|
|
637
637
|
});
|
|
638
|
+
|
|
639
|
+
it("keeps a read-only row to its owner header and Copy link", async () => {
|
|
640
|
+
const onCopyLink = vi.fn();
|
|
641
|
+
const onDelete = vi.fn();
|
|
642
|
+
act(() => {
|
|
643
|
+
root.render(
|
|
644
|
+
<ChatHistoryList
|
|
645
|
+
items={[
|
|
646
|
+
item({
|
|
647
|
+
id: "shared",
|
|
648
|
+
readOnly: true,
|
|
649
|
+
ownerAvatar: <span data-testid="avatar">P</span>,
|
|
650
|
+
ownerLabel: "pat@example.com",
|
|
651
|
+
accessLabel: "Shared with your organization",
|
|
652
|
+
accessBasis: "organization",
|
|
653
|
+
}),
|
|
654
|
+
]}
|
|
655
|
+
onSelect={() => {}}
|
|
656
|
+
onRename={() => {}}
|
|
657
|
+
onDelete={onDelete}
|
|
658
|
+
onTogglePin={() => {}}
|
|
659
|
+
onCopyLink={onCopyLink}
|
|
660
|
+
/>,
|
|
661
|
+
);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
const row = container.querySelector<HTMLElement>(".an-chat-history-row")!;
|
|
665
|
+
const mark = row.querySelector(".an-chat-history-row__owner-mark");
|
|
666
|
+
expect(mark?.getAttribute("data-access-basis")).toBe("organization");
|
|
667
|
+
expect(mark?.querySelector("[data-testid='avatar']")).not.toBeNull();
|
|
668
|
+
expect(
|
|
669
|
+
row.querySelector(".an-chat-history-row__topline")?.textContent,
|
|
670
|
+
).toBe("sharedP");
|
|
671
|
+
|
|
672
|
+
await openMenu(
|
|
673
|
+
row.querySelector<HTMLButtonElement>(
|
|
674
|
+
".an-chat-history-row__menu-trigger",
|
|
675
|
+
)!,
|
|
676
|
+
);
|
|
677
|
+
expect(
|
|
678
|
+
document.body.querySelector(".an-chat-history-row__menu-owner")
|
|
679
|
+
?.textContent,
|
|
680
|
+
).toBe("Ppat@example.comShared with your organization");
|
|
681
|
+
expect(getMenuItems().map((element) => element.textContent)).toEqual([
|
|
682
|
+
"Copy link",
|
|
683
|
+
]);
|
|
684
|
+
|
|
685
|
+
act(() => getMenuItems()[0]?.click());
|
|
686
|
+
expect(onCopyLink).toHaveBeenCalledWith("shared");
|
|
687
|
+
expect(onDelete).not.toHaveBeenCalled();
|
|
688
|
+
});
|
|
638
689
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
2
2
|
import {
|
|
3
3
|
IconDots,
|
|
4
|
+
IconLink,
|
|
4
5
|
IconPencil,
|
|
5
6
|
IconPinned,
|
|
6
7
|
IconPinnedOff,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
} from "@tabler/icons-react";
|
|
10
11
|
import React, { useMemo, useRef, useState } from "react";
|
|
11
12
|
|
|
12
|
-
import { Skeleton } from "../design-system/components.js";
|
|
13
|
+
import { Skeleton, Tooltip } from "../design-system/components.js";
|
|
13
14
|
import { cn } from "../utils.js";
|
|
14
15
|
|
|
15
16
|
/** How the viewer got access to a chat; the app supplies the translated copy. */
|
|
@@ -25,7 +26,12 @@ export interface ChatHistoryItem {
|
|
|
25
26
|
titleText?: string;
|
|
26
27
|
subtitle?: React.ReactNode;
|
|
27
28
|
detail?: React.ReactNode;
|
|
28
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* A shared row's owner mark, kept on one line beside the timestamp. Hovering
|
|
31
|
+
* it shows `ownerLabel` and `accessLabel`, which also head the row menu.
|
|
32
|
+
*/
|
|
33
|
+
ownerAvatar?: React.ReactNode;
|
|
34
|
+
/** Already-translated owner name for a shared row. */
|
|
29
35
|
ownerLabel?: React.ReactNode;
|
|
30
36
|
/** Already-translated access description, e.g. "Shared with you". */
|
|
31
37
|
accessLabel?: React.ReactNode;
|
|
@@ -33,9 +39,14 @@ export interface ChatHistoryItem {
|
|
|
33
39
|
timestamp?: React.ReactNode;
|
|
34
40
|
pinned?: boolean;
|
|
35
41
|
disabled?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The viewer can open the chat but not rename, pin or delete it, e.g. a chat
|
|
44
|
+
* someone shared. The menu keeps the owner header and Copy link.
|
|
45
|
+
*/
|
|
46
|
+
readOnly?: boolean;
|
|
36
47
|
/**
|
|
37
48
|
* Presentation only: drops the row menu and context menu while the row stays
|
|
38
|
-
* selectable.
|
|
49
|
+
* selectable, e.g. for a draft that has not been saved yet.
|
|
39
50
|
*/
|
|
40
51
|
hideActions?: boolean;
|
|
41
52
|
}
|
|
@@ -59,6 +70,7 @@ export interface ChatHistoryListLabels {
|
|
|
59
70
|
rename: string;
|
|
60
71
|
pin: string;
|
|
61
72
|
unpin: string;
|
|
73
|
+
copyLink: string;
|
|
62
74
|
delete: string;
|
|
63
75
|
}
|
|
64
76
|
|
|
@@ -72,6 +84,8 @@ export interface ChatHistoryListProps {
|
|
|
72
84
|
onRename?: (id: string, nextTitle: string) => void;
|
|
73
85
|
renameMaxLength?: number;
|
|
74
86
|
onDelete?: (id: string) => void;
|
|
87
|
+
/** Shown on every row, read-only ones included. */
|
|
88
|
+
onCopyLink?: (id: string) => void;
|
|
75
89
|
renderRowActions?: (item: ChatHistoryItem) => React.ReactNode;
|
|
76
90
|
renderAdditionalRowActions?: (
|
|
77
91
|
item: ChatHistoryItem,
|
|
@@ -104,6 +118,7 @@ const DEFAULT_LABELS: ChatHistoryListLabels = {
|
|
|
104
118
|
rename: "Rename",
|
|
105
119
|
pin: "Pin to top",
|
|
106
120
|
unpin: "Unpin from top",
|
|
121
|
+
copyLink: "Copy link",
|
|
107
122
|
delete: "Delete",
|
|
108
123
|
};
|
|
109
124
|
|
|
@@ -117,6 +132,7 @@ export function ChatHistoryList({
|
|
|
117
132
|
onRename,
|
|
118
133
|
renameMaxLength,
|
|
119
134
|
onDelete,
|
|
135
|
+
onCopyLink,
|
|
120
136
|
renderRowActions,
|
|
121
137
|
renderAdditionalRowActions,
|
|
122
138
|
searchValue,
|
|
@@ -141,9 +157,11 @@ export function ChatHistoryList({
|
|
|
141
157
|
rename: labels?.rename ?? DEFAULT_LABELS.rename,
|
|
142
158
|
pin: labels?.pin ?? DEFAULT_LABELS.pin,
|
|
143
159
|
unpin: labels?.unpin ?? DEFAULT_LABELS.unpin,
|
|
160
|
+
copyLink: labels?.copyLink ?? DEFAULT_LABELS.copyLink,
|
|
144
161
|
delete: labels?.delete ?? DEFAULT_LABELS.delete,
|
|
145
162
|
}),
|
|
146
163
|
[
|
|
164
|
+
labels?.copyLink,
|
|
147
165
|
labels?.delete,
|
|
148
166
|
labels?.options,
|
|
149
167
|
labels?.pin,
|
|
@@ -252,6 +270,7 @@ export function ChatHistoryList({
|
|
|
252
270
|
onRename={onRename}
|
|
253
271
|
renameMaxLength={renameMaxLength}
|
|
254
272
|
onDelete={onDelete}
|
|
273
|
+
onCopyLink={onCopyLink}
|
|
255
274
|
renderRowActions={renderRowActions}
|
|
256
275
|
renderAdditionalRowActions={renderAdditionalRowActions}
|
|
257
276
|
labels={resolvedLabels}
|
|
@@ -289,6 +308,7 @@ type ChatHistoryRowProps = {
|
|
|
289
308
|
onRename?: (id: string, nextTitle: string) => void;
|
|
290
309
|
renameMaxLength?: number;
|
|
291
310
|
onDelete?: (id: string) => void;
|
|
311
|
+
onCopyLink?: (id: string) => void;
|
|
292
312
|
renderRowActions?: (item: ChatHistoryItem) => React.ReactNode;
|
|
293
313
|
renderAdditionalRowActions?: (
|
|
294
314
|
item: ChatHistoryItem,
|
|
@@ -297,6 +317,21 @@ type ChatHistoryRowProps = {
|
|
|
297
317
|
labels: ChatHistoryListLabels;
|
|
298
318
|
};
|
|
299
319
|
|
|
320
|
+
function ChatHistoryOwnerSummary({ item }: { item: ChatHistoryItem }) {
|
|
321
|
+
return (
|
|
322
|
+
<span className="an-chat-history-owner">
|
|
323
|
+
{item.ownerLabel != null && (
|
|
324
|
+
<span className="an-chat-history-owner__name">{item.ownerLabel}</span>
|
|
325
|
+
)}
|
|
326
|
+
{item.accessLabel != null && (
|
|
327
|
+
<span className="an-chat-history-owner__access">
|
|
328
|
+
{item.accessLabel}
|
|
329
|
+
</span>
|
|
330
|
+
)}
|
|
331
|
+
</span>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
300
335
|
const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
301
336
|
item,
|
|
302
337
|
active,
|
|
@@ -306,6 +341,7 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
306
341
|
onRename,
|
|
307
342
|
renameMaxLength,
|
|
308
343
|
onDelete,
|
|
344
|
+
onCopyLink,
|
|
309
345
|
renderRowActions,
|
|
310
346
|
renderAdditionalRowActions,
|
|
311
347
|
labels,
|
|
@@ -315,12 +351,13 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
315
351
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
316
352
|
const renameInputRef = useRef<HTMLInputElement | null>(null);
|
|
317
353
|
|
|
354
|
+
const editable = !item.readOnly;
|
|
355
|
+
const hasOwner = item.ownerLabel != null || item.accessLabel != null;
|
|
318
356
|
const hasMenu =
|
|
319
357
|
!item.hideActions &&
|
|
320
358
|
Boolean(
|
|
321
|
-
onTogglePin ||
|
|
322
|
-
|
|
323
|
-
onDelete ||
|
|
359
|
+
(editable && (onTogglePin || onRename || onDelete)) ||
|
|
360
|
+
onCopyLink ||
|
|
324
361
|
renderRowActions ||
|
|
325
362
|
renderAdditionalRowActions,
|
|
326
363
|
);
|
|
@@ -402,6 +439,22 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
402
439
|
>
|
|
403
440
|
<div className="an-chat-history-row__topline">
|
|
404
441
|
<span className="an-chat-history-row__title">{item.title}</span>
|
|
442
|
+
{item.ownerAvatar != null && (
|
|
443
|
+
<Tooltip
|
|
444
|
+
trigger={
|
|
445
|
+
<span
|
|
446
|
+
className="an-chat-history-row__owner-mark"
|
|
447
|
+
data-access-basis={item.accessBasis}
|
|
448
|
+
>
|
|
449
|
+
{item.ownerAvatar}
|
|
450
|
+
</span>
|
|
451
|
+
}
|
|
452
|
+
content={
|
|
453
|
+
hasOwner ? <ChatHistoryOwnerSummary item={item} /> : null
|
|
454
|
+
}
|
|
455
|
+
disabled={!hasOwner}
|
|
456
|
+
/>
|
|
457
|
+
)}
|
|
405
458
|
{item.timestamp != null && (
|
|
406
459
|
<span className="an-chat-history-row__timestamp">
|
|
407
460
|
{item.timestamp}
|
|
@@ -414,23 +467,6 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
414
467
|
{item.detail != null && (
|
|
415
468
|
<div className="an-chat-history-row__detail">{item.detail}</div>
|
|
416
469
|
)}
|
|
417
|
-
{(item.ownerLabel != null || item.accessLabel != null) && (
|
|
418
|
-
<div
|
|
419
|
-
className="an-chat-history-row__access"
|
|
420
|
-
data-access-basis={item.accessBasis}
|
|
421
|
-
>
|
|
422
|
-
{item.ownerLabel != null && (
|
|
423
|
-
<span className="an-chat-history-row__owner">
|
|
424
|
-
{item.ownerLabel}
|
|
425
|
-
</span>
|
|
426
|
-
)}
|
|
427
|
-
{item.accessLabel != null && (
|
|
428
|
-
<span className="an-chat-history-row__access-label">
|
|
429
|
-
{item.accessLabel}
|
|
430
|
-
</span>
|
|
431
|
-
)}
|
|
432
|
-
</div>
|
|
433
|
-
)}
|
|
434
470
|
</button>
|
|
435
471
|
)}
|
|
436
472
|
|
|
@@ -463,11 +499,22 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
463
499
|
side="bottom"
|
|
464
500
|
sideOffset={4}
|
|
465
501
|
>
|
|
502
|
+
{hasOwner && (
|
|
503
|
+
<div
|
|
504
|
+
className="an-chat-history-row__menu-owner"
|
|
505
|
+
data-access-basis={item.accessBasis}
|
|
506
|
+
>
|
|
507
|
+
{item.ownerAvatar != null && (
|
|
508
|
+
<span aria-hidden="true">{item.ownerAvatar}</span>
|
|
509
|
+
)}
|
|
510
|
+
<ChatHistoryOwnerSummary item={item} />
|
|
511
|
+
</div>
|
|
512
|
+
)}
|
|
466
513
|
{renderRowActions ? (
|
|
467
514
|
renderRowActions(item)
|
|
468
515
|
) : (
|
|
469
516
|
<>
|
|
470
|
-
{onRename && (
|
|
517
|
+
{editable && onRename && (
|
|
471
518
|
<button
|
|
472
519
|
type="button"
|
|
473
520
|
role="menuitem"
|
|
@@ -478,7 +525,7 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
478
525
|
<span>{labels.rename}</span>
|
|
479
526
|
</button>
|
|
480
527
|
)}
|
|
481
|
-
{onTogglePin && (
|
|
528
|
+
{editable && onTogglePin && (
|
|
482
529
|
<button
|
|
483
530
|
type="button"
|
|
484
531
|
role="menuitem"
|
|
@@ -496,10 +543,24 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
|
|
|
496
543
|
<span>{item.pinned ? labels.unpin : labels.pin}</span>
|
|
497
544
|
</button>
|
|
498
545
|
)}
|
|
546
|
+
{onCopyLink && (
|
|
547
|
+
<button
|
|
548
|
+
type="button"
|
|
549
|
+
role="menuitem"
|
|
550
|
+
className="an-chat-history-row__menu-item"
|
|
551
|
+
onClick={() => {
|
|
552
|
+
setMenuOpen(false);
|
|
553
|
+
onCopyLink(item.id);
|
|
554
|
+
}}
|
|
555
|
+
>
|
|
556
|
+
<IconLink size={13} strokeWidth={1.8} />
|
|
557
|
+
<span>{labels.copyLink}</span>
|
|
558
|
+
</button>
|
|
559
|
+
)}
|
|
499
560
|
{renderAdditionalRowActions?.(item, () =>
|
|
500
561
|
setMenuOpen(false),
|
|
501
562
|
)}
|
|
502
|
-
{onDelete && (
|
|
563
|
+
{editable && onDelete && (
|
|
503
564
|
<button
|
|
504
565
|
type="button"
|
|
505
566
|
role="menuitem"
|
|
@@ -273,7 +273,7 @@ describe("ChatHistoryRail sections", () => {
|
|
|
273
273
|
expect(onLoadMore).toHaveBeenCalledOnce();
|
|
274
274
|
});
|
|
275
275
|
|
|
276
|
-
it("
|
|
276
|
+
it("keeps a shared row on one line with the owner mark", () => {
|
|
277
277
|
renderRail([
|
|
278
278
|
{
|
|
279
279
|
id: "shared",
|
|
@@ -281,16 +281,24 @@ describe("ChatHistoryRail sections", () => {
|
|
|
281
281
|
{
|
|
282
282
|
id: "s1",
|
|
283
283
|
title: "Roadmap",
|
|
284
|
+
ownerAvatar: <span>P</span>,
|
|
284
285
|
ownerLabel: "Pat Lee",
|
|
285
286
|
accessLabel: "Shared with your organization",
|
|
286
287
|
accessBasis: "organization",
|
|
288
|
+
readOnly: true,
|
|
287
289
|
},
|
|
288
290
|
],
|
|
289
291
|
},
|
|
290
292
|
]);
|
|
291
|
-
const
|
|
292
|
-
expect(
|
|
293
|
-
|
|
293
|
+
const row = container.querySelector(".an-chat-history-row")!;
|
|
294
|
+
expect(
|
|
295
|
+
row
|
|
296
|
+
.querySelector(".an-chat-history-row__owner-mark")
|
|
297
|
+
?.getAttribute("data-access-basis"),
|
|
298
|
+
).toBe("organization");
|
|
299
|
+
expect(row.querySelector(".an-chat-history-row__button")?.textContent).toBe(
|
|
300
|
+
"RoadmapP",
|
|
301
|
+
);
|
|
294
302
|
});
|
|
295
303
|
|
|
296
304
|
it("selecting a section row and New chat work as in the flat rail", () => {
|