Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve chatbot integration + css fixes #2872

Merged
merged 7 commits into from
Dec 4, 2024
1 change: 1 addition & 0 deletions apps/backoffice-v2/src/common/env/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ export const EnvSchema = z.object({
return new RegExp(value);
}, z.custom<RegExp>(value => value instanceof RegExp).optional()),
VITE_SAOLA_API_KEY: z.string().optional(),
VITE_BOTPRESS_CLIENT_ID: z.string().default('8f29c89d-ec0e-494d-b18d-6c3590b28be6'),
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved
});
60 changes: 51 additions & 9 deletions apps/backoffice-v2/src/domains/chat/chatbot-opengpt.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,80 @@
import { getClient, Webchat, WebchatProvider } from '@botpress/webchat';
import { getClient, Webchat, WebchatProvider, WebchatClient } from '@botpress/webchat';
import { buildTheme } from '@botpress/webchat-generator';
import { useEffect } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useAuthenticatedUserQuery } from '../../domains/auth/hooks/queries/useAuthenticatedUserQuery/useAuthenticatedUserQuery';
import { useCurrentCaseQuery } from '../../pages/Entity/hooks/useCurrentCaseQuery/useCurrentCaseQuery';
import { useParams } from 'react-router-dom';

// declare const themeNames: readonly ["prism", "galaxy", "dusk", "eggplant", "dawn", "midnight"];
const { theme, style } = buildTheme({
themeName: 'galaxy',
themeColor: 'blue',
});

const clientId = '8f29c89d-ec0e-494d-b18d-6c3590b28be6';

const Chatbot = ({
isWebchatOpen,
toggleIsWebchatOpen,
botpressClientId,
}: {
isWebchatOpen: boolean;
toggleIsWebchatOpen: () => void;
botpressClientId: string;
}) => {
const client = getClient({ clientId });
const [client, setClient] = useState<WebchatClient | null>(null);
const { data: session } = useAuthenticatedUserQuery();
const { data: currentCase } = useCurrentCaseQuery();
const { entityId: caseId } = useParams();

const sendCurrentCaseData = useCallback(
async (botpressClient: WebchatClient | null = client) => {
if (!currentCase || !botpressClient) {
return;
}

try {
await botpressClient.sendEvent({
type: 'case-data',
data: currentCase.context,
});
} catch (error) {
console.error('Failed to send case data:', error);
}
},
[currentCase, client],
);

useEffect(() => {
if (session?.user) {
const { firstName, lastName, email } = session.user;
void client.updateUser({
if (client || !botpressClientId || !session?.user) {
return;
}

const { firstName, lastName, email } = session.user;
const botpressClientInstance = getClient({ clientId: botpressClientId });
setClient(botpressClientInstance);

botpressClientInstance.on('conversation', (ev: any) => {
void botpressClientInstance.updateUser({
data: {
firstName,
lastName,
email,
},
});
setTimeout(() => {
void sendCurrentCaseData(botpressClientInstance);
}, 0);
});
}, [session, client, sendCurrentCaseData, botpressClientId]);

useEffect(() => {
if (caseId) {
void sendCurrentCaseData();
}
}, [session, client]);
}, [caseId, sendCurrentCaseData]);

if (!client) {
return null;
}

return (
<div>
Expand Down
4 changes: 3 additions & 1 deletion apps/backoffice-v2/src/domains/customer/fetchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const CustomerSchema = z.object({
language: z.union([z.string(), z.null()]).optional(),
features: z
.object({
chatbot: z
.object({ enabled: z.boolean().default(false), clientId: z.string().optional() })
.optional(),
createBusinessReport: z
.object({ enabled: z.boolean().default(false), options: createBusinessReportOptions })
.optional(),
Expand All @@ -35,7 +38,6 @@ const CustomerSchema = z.object({
isMerchantMonitoringEnabled: z.boolean().default(false),
isExample: z.boolean().default(false),
isDemo: z.boolean().default(false),
isChatbotEnabled: z.boolean().default(false),
})
.nullable()
.default({
Expand Down
22 changes: 20 additions & 2 deletions apps/backoffice-v2/src/pages/Root/Root.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { ServerDownLayout } from './ServerDown.layout';
import { useCustomerQuery } from '@/domains/customer/hooks/queries/useCustomerQuery/useCustomerQuery';
import { FullScreenLoader } from '@/common/components/molecules/FullScreenLoader/FullScreenLoader';
import Chatbot from '@/domains/chat/chatbot-opengpt';
import { RenderChildrenInIFrame } from '@/common/components/organisms/RenderChildrenInIFrame/RenderChildrenInIFrame';
import { ctw } from '@/common/utils/ctw/ctw';
import { env } from '@/common/env/env';

const ReactQueryDevtools = lazy(() =>
process.env.NODE_ENV !== 'production'
Expand All @@ -25,11 +28,26 @@ const ChatbotLayout: FunctionComponent = () => {
return <FullScreenLoader />;
}

if (!customer?.config?.isChatbotEnabled) {
if (!customer?.features?.chatbot?.enabled) {
return null;
}

return <Chatbot isWebchatOpen={isWebchatOpen} toggleIsWebchatOpen={toggleIsWebchatOpen} />;
const botpressClientId = customer?.features?.chatbot?.clientId || env.VITE_BOTPRESS_CLIENT_ID;

return (
<RenderChildrenInIFrame
className={ctw('fixed bottom-right-0', {
'h-[700px] w-[400px]': isWebchatOpen,
'd-[80px]': !isWebchatOpen,
})}
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved
>
<Chatbot
isWebchatOpen={isWebchatOpen}
toggleIsWebchatOpen={toggleIsWebchatOpen}
botpressClientId={botpressClientId}
/>
</RenderChildrenInIFrame>
);
};

export const Root: FunctionComponent = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ export const WorkflowConfigSchema = Type.Object({
hasUboOngoingMonitoring: Type.Optional(Type.Boolean()),
maxBusinessReports: Type.Optional(Type.Number()),
isMerchantMonitoringEnabled: Type.Optional(Type.Boolean()),
isChatbotEnabled: Type.Optional(Type.Boolean()),
});

export type TWorkflowConfig = Static<typeof WorkflowConfigSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export const ConfigSchema = z
hasUboOngoingMonitoring: z.boolean().optional(),
maxBusinessReports: z.number().nonnegative().optional(),
isMerchantMonitoringEnabled: z.boolean().optional(),
isChatbotEnabled: z.boolean().optional(),
uiOptions: z
.object({
redirectUrls: z
Expand Down
Loading