Skip to content

Commit

Permalink
feat: improve chatbot integration + css fixes (#2872)
Browse files Browse the repository at this point in the history
* feat(chatbot): enhance chatbot functionality with case data handling

- Add client as a prop to Chatbot component
- Implement sending current case data to chatbot
- Improve environment variable usage for client ID

(Your code is like a bad magician—now you see the client, now you don’t)

* feat(chatbot): wrap chatbot in iframe component

- Import RenderChildrenInIFrame to contain the Chatbot
- Adjust resizing behavior based on chatbot visibility

(It's about time that chatbot got some boundaries; it was getting a bit too cozy)

* feat(chatbot): add configurable client ID for chatbot integration

- Introduce VITE_BOTPRESS_CLIENT_ID to environment schema
- Update Chatbot component to utilize dynamic client ID
- Adjust customer features to include chatbot configuration

(If your chatbot was any less reliable, it would be giving out horoscopes instead of responses)

* chore(chatbot): remove unnecessary chatbot enable flags

- Remove redundant isChatbotEnabled flags from schemas
- Clean up caseId assignment placement in chatbot component

(Your code is so clean, it's practically begging for a dust bunny)

* refactor(chatbot): streamline chatbot client management

- Remove unused WebchatClient state from ChatbotLayout
- Change variable names for clarity and consistency
- Update useEffect hooks to handle new parameter definitions

(With all these changes, I half-expect the chatbot to start giving better life advice)

* refactor(customer): rename 'isEnabled' to 'enabled' for clarity

- Update CustomerSchema to use 'enabled' instead of 'isEnabled'
- Adjust conditional check in ChatbotLayout for consistency

(your naming conventions are so confusing, they should come with a user manual)

---------

Co-authored-by: Tomer Shvadron <[email protected]>
  • Loading branch information
shanegrouber and tomer-shvadron authored Dec 4, 2024
1 parent 6d6d78b commit 786d520
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 14 deletions.
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'),
});
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,
})}
>
<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

0 comments on commit 786d520

Please sign in to comment.