Skip to content

Commit 7130f9a

Browse files
[Dashboard] siwa chat widget (#7128)
Co-authored-by: Joaquim Verges <joaquim.verges@gmail.com>
1 parent 1e0b142 commit 7130f9a

File tree

14 files changed

+569
-50
lines changed

14 files changed

+569
-50
lines changed

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getContractMetadata } from "thirdweb/extensions/common";
88
import { isAddress, isContractDeployed } from "thirdweb/utils";
99
import { shortenIfAddress } from "utils/usedapp-external";
1010
import { NebulaChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
11+
import { examplePrompts } from "../../../../../nebula-app/(app)/data/examplePrompts";
1112
import {
1213
getAuthTokenWalletAddress,
1314
getUserThirdwebClient,
@@ -94,14 +95,6 @@ Users may be considering integrating the contract into their applications. Discu
9495
9596
The following is the user's message:`;
9697

97-
const examplePrompts: string[] = [
98-
"What does this contract do?",
99-
"What permissions or roles exist in this contract?",
100-
"Which functions are used the most?",
101-
"Has this contract been used recently?",
102-
"Who are the largest holders/users of this?",
103-
];
104-
10598
return (
10699
<ContractPageLayout
107100
chainMetadata={chainMetadata}
@@ -124,10 +117,7 @@ The following is the user's message:`;
124117
chainIds: [chainId],
125118
wallet: accountAddress ?? undefined,
126119
}}
127-
examplePrompts={examplePrompts.map((prompt) => ({
128-
title: prompt,
129-
message: prompt,
130-
}))}
120+
examplePrompts={examplePrompts}
131121
/>
132122
{props.children}
133123
</ContractPageLayout>

apps/dashboard/src/app/(app)/(dashboard)/support/page.tsx

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Button } from "@/components/ui/button";
22
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3-
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
43
import { BookOpenIcon, ChevronRightIcon } from "lucide-react";
54
import type { Metadata } from "next";
65
import Image from "next/image";
@@ -10,7 +9,8 @@ import contractsIcon from "../../../../../public/assets/support/contracts.png";
109
import engineIcon from "../../../../../public/assets/support/engine.png";
1110
import miscIcon from "../../../../../public/assets/support/misc.svg";
1211
import connectIcon from "../../../../../public/assets/support/wallets.png";
13-
import { NebulaChatButton } from "../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
12+
import { getTeams } from "../../../../@/api/team";
13+
import { CustomChatButton } from "../../../nebula-app/(app)/components/CustomChat/CustomChatButton";
1414
import {
1515
getAuthToken,
1616
getAuthTokenWalletAddress,
@@ -118,25 +118,22 @@ const HELP_PRODUCTS = [
118118
},
119119
] as const;
120120

121+
export const siwaExamplePrompts = [
122+
"How do I add in-app wallet with sign in with google to my react app?",
123+
"How do I send a transaction in Unity?",
124+
"What does this contract revert error mean?",
125+
"I see thirdweb support id in my console log, can you help me?",
126+
"Here is my code, can you tell me why I'm seeing this error?",
127+
];
128+
121129
export default async function SupportPage() {
122130
const [authToken, accountAddress] = await Promise.all([
123131
getAuthToken(),
124132
getAuthTokenWalletAddress(),
125133
]);
126134

127-
const client = getClientThirdwebClient({
128-
jwt: authToken,
129-
teamId: undefined,
130-
});
131-
132-
const supportPromptPrefix =
133-
"You are a Customer Success Agent at thirdweb, assisting customers with blockchain and Web3-related issues. Use the following details to craft a professional, empathetic response: ";
134-
const examplePrompts = [
135-
"ERC20 - Transfer Amount Exceeds Allowance",
136-
"Replacement transaction underpriced / Replacement fee too low",
137-
"Nonce too low: next nonce #, tx nonce #",
138-
"Nonce too high",
139-
];
135+
const teams = await getTeams();
136+
const teamId = teams?.[0]?.id ?? undefined;
140137

141138
return (
142139
<main className="flex flex-col gap-12 pb-12">
@@ -157,22 +154,16 @@ export default async function SupportPage() {
157154
team.
158155
</p>
159156
<div className="mt-6 flex w-full flex-col items-center gap-3">
160-
<NebulaChatButton
157+
<CustomChatButton
161158
isLoggedIn={!!accountAddress}
162159
networks="all"
163160
isFloating={false}
164161
pageType="support"
165-
label="Ask Nebula AI for support"
166-
client={client}
167-
nebulaParams={{
168-
messagePrefix: supportPromptPrefix,
169-
chainIds: [],
170-
wallet: accountAddress ?? undefined,
171-
}}
172-
examplePrompts={examplePrompts.map((prompt) => ({
173-
title: prompt,
174-
message: prompt,
175-
}))}
162+
label="Ask AI for support"
163+
examplePrompts={siwaExamplePrompts}
164+
authToken={authToken || undefined}
165+
teamId={teamId}
166+
clientId={undefined}
176167
/>
177168

178169
<Link

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { AppFooter } from "@/components/blocks/app-footer";
44
import { TabPathLinks } from "@/components/ui/tabs";
55
import { AnnouncementBanner } from "components/notices/AnnouncementBanner";
66
import { redirect } from "next/navigation";
7+
import { siwaExamplePrompts } from "../../../(dashboard)/support/page";
78
import { getClientThirdwebClient } from "../../../../../@/constants/thirdweb-client.client";
9+
import { CustomChatButton } from "../../../../nebula-app/(app)/components/CustomChat/CustomChatButton";
810
import { getValidAccount } from "../../../account/settings/getAccount";
911
import {
1012
getAuthToken,
@@ -91,6 +93,19 @@ export default async function TeamLayout(props: {
9193
</div>
9294

9395
<main className="flex grow flex-col">{props.children}</main>
96+
<div className="fixed right-6 bottom-6 z-50">
97+
<CustomChatButton
98+
clientId={undefined}
99+
isLoggedIn={true}
100+
networks="all"
101+
isFloating={true}
102+
pageType="support"
103+
label="Ask AI Assistant"
104+
examplePrompts={siwaExamplePrompts}
105+
teamId={team.id}
106+
authToken={authToken}
107+
/>
108+
</div>
94109
<AppFooter />
95110
</div>
96111
);

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/layout.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { getTeams } from "@/api/team";
33
import { SidebarProvider } from "@/components/ui/sidebar";
44
import { AnnouncementBanner } from "components/notices/AnnouncementBanner";
55
import { redirect } from "next/navigation";
6+
import { siwaExamplePrompts } from "../../../(dashboard)/support/page";
67
import { getClientThirdwebClient } from "../../../../../@/constants/thirdweb-client.client";
8+
import { CustomChatButton } from "../../../../nebula-app/(app)/components/CustomChat/CustomChatButton";
79
import { getValidAccount } from "../../../account/settings/getAccount";
810
import {
911
getAuthToken,
@@ -78,6 +80,19 @@ export default async function ProjectLayout(props: {
7880
{props.children}
7981
</ProjectSidebarLayout>
8082
</div>
83+
<div className="fixed right-6 bottom-6 z-50">
84+
<CustomChatButton
85+
isLoggedIn={true}
86+
networks="all"
87+
isFloating={true}
88+
pageType="support"
89+
label="Ask AI Assistant"
90+
examplePrompts={siwaExamplePrompts}
91+
teamId={team.id}
92+
clientId={project.publishableKey}
93+
authToken={authToken}
94+
/>
95+
</div>
8196
<SaveLastUsedProject projectId={project.id} teamId={team.id} />
8297
</SidebarProvider>
8398
);

apps/dashboard/src/app/(app)/team/[team_slug]/layout.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ArrowRightIcon } from "lucide-react";
55
import Link from "next/link";
66
import { redirect } from "next/navigation";
77
import { Suspense } from "react";
8+
import { getAuthToken } from "../../api/lib/getAuthToken";
89
import { EnsureValidConnectedWalletLoginServer } from "../../components/EnsureValidConnectedWalletLogin/EnsureValidConnectedWalletLoginServer";
910
import { isTeamOnboardingComplete } from "../../login/onboarding/isOnboardingRequired";
1011
import { SaveLastVisitedTeamPage } from "../components/last-visited-page/SaveLastVisitedPage";
@@ -18,12 +19,17 @@ export default async function RootTeamLayout(props: {
1819
params: Promise<{ team_slug: string }>;
1920
}) {
2021
const { team_slug } = await props.params;
22+
const authToken = await getAuthToken();
2123
const team = await getTeamBySlug(team_slug).catch(() => null);
2224

2325
if (!team) {
2426
redirect("/team");
2527
}
2628

29+
if (!authToken) {
30+
redirect("/login");
31+
}
32+
2733
if (!isTeamOnboardingComplete(team)) {
2834
redirect(`/get-started/team/${team.slug}`);
2935
}

apps/dashboard/src/app/nebula-app/(app)/components/ChatBar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export function ChatBar(props: {
6868
isConnectingWallet: boolean;
6969
allowImageUpload: boolean;
7070
onLoginClick: undefined | (() => void);
71+
placeholder: string;
7172
}) {
7273
const [message, setMessage] = useState(props.prefillMessage || "");
7374
const selectedChainIds = props.context?.chainIds?.map((x) => Number(x)) || [];
@@ -142,7 +143,7 @@ export function ChatBar(props: {
142143
<div className="p-2">
143144
<div className="max-h-[200px] overflow-y-auto">
144145
<AutoResizeTextarea
145-
placeholder={"Ask Nebula"}
146+
placeholder={props.placeholder}
146147
value={message}
147148
onChange={(e) => setMessage(e.target.value)}
148149
onKeyDown={(e) => {

apps/dashboard/src/app/nebula-app/(app)/components/ChatPageContent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ export function ChatPageContent(props: {
339339

340340
{messages.length > 0 && (
341341
<Chats
342+
teamId={undefined}
342343
messages={messages}
343344
isChatStreaming={isChatStreaming}
344345
authToken={props.authToken}
@@ -353,6 +354,7 @@ export function ChatPageContent(props: {
353354

354355
<div className="container max-w-[800px]">
355356
<ChatBar
357+
placeholder="Ask Nebula"
356358
isConnectingWallet={connectionStatus === "connecting"}
357359
showContextSelector={true}
358360
connectedWallets={connectedWalletsMeta}

apps/dashboard/src/app/nebula-app/(app)/components/Chatbar.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ function Variant(props: {
166166
return (
167167
<BadgeContainer label={props.label}>
168168
<ChatBar
169+
placeholder={"Ask Nebula"}
169170
isConnectingWallet={props.isConnectingWallet || false}
170171
client={storybookThirdwebClient}
171172
abortChatStream={() => {}}

apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ function Variant(props: {
227227
}) {
228228
return (
229229
<Chats
230+
teamId={undefined}
230231
enableAutoScroll={false}
231232
setEnableAutoScroll={() => {}}
232233
client={storybookThirdwebClient}

0 commit comments

Comments
 (0)