Skip to content

Commit

Permalink
Chat widget fixes (#5414)
Browse files Browse the repository at this point in the history
* Chat widget fixes

* Import only used material icons

* Style chat widget

---------

Co-authored-by: Carlos Cano <[email protected]>
  • Loading branch information
me-andre and ccanos authored Jan 22, 2024
1 parent 2cbc1e7 commit 282d74d
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 50 deletions.
14 changes: 8 additions & 6 deletions src/core/i18n/en/translation.en.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
{
"chatbot": {
"title": "Alkemio Help",
"subtitle": "Ask your question to search through our documentation or browse it directly",
"title": "Help",
"intro": "Hi, this is Alkemio’s automated guidance chat. It can provide you with answers based on Alkemio’s documentation. What are you looking for?",
"infoDialog": {
"title": "Alkemio Help",
"content": "The Alkemio guidance chat is an advanced search module that helps you by automatically generating an answer to your question based on Alkemio’s documentation. There are no people on the other side of the screen ;-). If you want to reach someone from the Alkemio team, please use the contact button below.\nAnswers (and sources) returned here are based on content from the Alkemio help center. The interaction is with a widely used online generative AI engine, which is able to interpret your question and provide guidance as to the most relevant help. There is no user data involved, and interaction with the search engine cannot be linked to individual users."
"content": "Use the Alkemio guidance chat to get automatic answers to your questions from Alkemio’s documentation.\n\nThis is an __advanced search module__ powered by a widely used online generative AI engine. It interprets your question and guides you to the most relevant help from the Alkemio help center. You can see the sources of the answers as well.\n\n__Don’t worry about your privacy:__ the search engine does not use or store any user data, and it cannot link the interaction to individual users. If you need to contact the Alkemio team, please click the contact button below."
},
"feedback": {
"message": "Is the answer relevant?",
Expand All @@ -17,15 +16,18 @@
},
"references": [
{
"uri": "https://www.alkemio.org/help/getting-started/",
"icon": "GradeOutlined",
"uri": "https://welcome.alkem.io/help/getting-started/",
"title": "New user? Visit our Getting Started pages!"
},
{
"uri": "https://www.alkemio.org/help/",
"icon": "NotListedLocationOutlined",
"uri": "https://welcome.alkem.io/help/",
"title": "Find your answers in the Help Center or FAQ"
},
{
"uri": "https://www.alkemio.org/support/",
"icon": "EmailOutlined",
"uri": "https://welcome.alkem.io/contact/",
"title": "Contact the Alkemio team"
}
]
Expand Down
3 changes: 2 additions & 1 deletion src/core/ui/markdown/MarkdownOptionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { createContext, PropsWithChildren, useContext } from 'react';

export interface MarkdownOptions {
card: boolean;
flat: boolean;
plain: boolean;
multiline: boolean;
disableParagraphPadding: boolean;
caption: boolean;
}

const MarkdownOptionsContext = createContext<MarkdownOptions | undefined>(undefined);
Expand Down
2 changes: 1 addition & 1 deletion src/core/ui/markdown/OneLineMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface OneLineMarkdownProps {
*/
const OneLineMarkdown = ({ children }: OneLineMarkdownProps) => {
return (
<WrapperMarkdown flat card>
<WrapperMarkdown plain card>
{children}
</WrapperMarkdown>
);
Expand Down
12 changes: 7 additions & 5 deletions src/core/ui/markdown/WrapperMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@ export interface MarkdownProps extends ReactMarkdownOptions, Partial<MarkdownOpt

export const WrapperMarkdown = ({
card = false,
flat = false,
multiline = !flat,
plain = false,
multiline = !plain,
disableParagraphPadding = card,
caption = false,
...props
}: MarkdownProps) => {
return (
<MarkdownOptionsProvider
card={card}
flat={flat}
plain={plain}
multiline={multiline}
disableParagraphPadding={disableParagraphPadding}
caption={caption}
>
<ReactMarkdown
components={components}
remarkPlugins={[gfm, [PlainText, { enabled: flat }]]}
remarkPlugins={[gfm, [PlainText, { enabled: plain }]]}
rehypePlugins={
flat ? undefined : ([rehypeRaw, { passThrough: allowedNodeTypes }] as MarkdownProps['rehypePlugins'])
plain ? undefined : ([rehypeRaw, { passThrough: allowedNodeTypes }] as MarkdownProps['rehypePlugins'])
}
{...props}
/>
Expand Down
6 changes: 3 additions & 3 deletions src/core/ui/markdown/components/MarkdownParagraph.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { ReactMarkdownProps } from 'react-markdown/lib/complex-types';
import { CardText, Text } from '../../typography';
import { Caption, CardText, Text } from '../../typography';
import { gutters } from '../../grid/utils';
import { useMarkdownOptions } from '../MarkdownOptionsContext';

Expand All @@ -9,9 +9,9 @@ interface MarkdownParagraphProps extends ReactMarkdownProps {
}

const MarkdownParagraph = ({ node, overrideDisableParagraphPadding, ...props }: MarkdownParagraphProps) => {
const { card, multiline, disableParagraphPadding } = useMarkdownOptions();
const { card, multiline, caption, disableParagraphPadding } = useMarkdownOptions();

const Component = card ? CardText : Text;
const Component = caption ? Caption : card ? CardText : Text;

const disableMargin = overrideDisableParagraphPadding ?? disableParagraphPadding;
return <Component noWrap={!multiline} marginY={disableMargin ? 0 : gutters(0.5)} {...props} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const TopCalloutDetails = ({ title, description, activity, type, calloutUri }: T
},
}}
>
<WrapperMarkdown card flat multiline>
<WrapperMarkdown card plain multiline>
{description}
</WrapperMarkdown>
</CardText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const InvitationCardHorizontal = ({ invitation, onClick }: InvitationCardHorizon
noWrap
>
{invitation.welcomeMessage && (
<WrapperMarkdown card flat>
<WrapperMarkdown card plain>
{invitation.welcomeMessage}
</WrapperMarkdown>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React, { PropsWithChildren } from 'react';
import React, { ComponentType, PropsWithChildren } from 'react';
import RouterLink from '../../../../core/ui/link/RouterLink';
import { Text } from '../../../../core/ui/typography';
import { Box } from '@mui/material';
import { Box, SvgIconProps } from '@mui/material';
import { gutters } from '../../../../core/ui/grid/utils';
import { OpenInNewOutlined } from '@mui/icons-material';

interface ReferencesListSmallItemProps {
uri: string;
iconComponent?: ComponentType<SvgIconProps>;
}

const ReferencesListSmallItem = ({ uri, children }: PropsWithChildren<ReferencesListSmallItemProps>) => {
const ReferencesListSmallItem = ({
uri,
iconComponent: Icon = OpenInNewOutlined,
children,
}: PropsWithChildren<ReferencesListSmallItemProps>) => {
return (
<Box component={RouterLink} to={uri} display="flex" gap={gutters(0.5)} alignItems="center">
<OpenInNewOutlined fontSize="inherit" />
<Icon fontSize="inherit" />
<Text>{children}</Text>
</Box>
);
Expand Down
9 changes: 3 additions & 6 deletions src/main/guidance/chatWidget/ChatWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cloneElement, ReactElement, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { Box, IconButton, IconButtonProps, Paper, SvgIconProps, Theme, Tooltip, useMediaQuery } from '@mui/material';
import { Box, IconButton, IconButtonProps, Paper, SvgIconProps, Theme, Tooltip } from '@mui/material';
import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt';
import ThumbDownOffAltIcon from '@mui/icons-material/ThumbDownOffAlt';
import { addResponseMessage, dropMessages, renderCustomComponent, toggleWidget, Widget } from 'react-chat-widget';
Expand All @@ -14,7 +14,6 @@ import 'react-chat-widget/lib/styles.css';
import formatChatGuidanceResponseAsMarkdown from './formatChatGuidanceResponseAsMarkdown';
import ChatWidgetStyles from './ChatWidgetStyles';
import ChatWidgetTitle from './ChatWidgetTitle';
import ChatWidgetSubtitle from './ChatWidgetSubtitle';
import ChatWidgetHelpDialog from './ChatWidgetHelpDialog';
import { createPortal } from 'react-dom';
import ChatWidgetFooter from './ChatWidgetFooter';
Expand Down Expand Up @@ -213,8 +212,6 @@ const ChatWidget = () => {

useLayoutEffect(setupMenuButton, [chatToggleTime]);

const isMobile = useMediaQuery('(orientation: portrait)');

const [resetChatGuidance] = useResetChatGuidanceMutation();

const handleClearChat = () => {
Expand All @@ -228,8 +225,8 @@ const ChatWidget = () => {
<ChatWidgetStyles ref={wrapperRef} aria-label={t('common.help')}>
<Widget
profileAvatar={logoSrc}
title={<ChatWidgetTitle mobile={isMobile} onClickInfo={() => setIsHelpDialogOpen(true)} />}
subtitle={<ChatWidgetSubtitle />}
title={<ChatWidgetTitle onClickInfo={() => setIsHelpDialogOpen(true)} />}
subtitle={<></>}
handleNewUserMessage={setNewMessage}
handleToggle={() => setChatToggleTime(Date.now())}
/>
Expand Down
16 changes: 13 additions & 3 deletions src/main/guidance/chatWidget/ChatWidgetFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import ReferencesListSmallItem from '../../../domain/profile/Reference/Reference
import { useTranslation } from 'react-i18next';
import SwapColors from '../../../core/ui/palette/SwapColors';
import { Paper } from '@mui/material';
import { EmailOutlined, GradeOutlined, NotListedLocationOutlined } from '@mui/icons-material';
import { gutters } from '../../../core/ui/grid/utils';

const Icons = {
GradeOutlined,
NotListedLocationOutlined,
EmailOutlined,
};

const ChatWidgetFooter = () => {
const { t } = useTranslation();
Expand All @@ -12,9 +20,11 @@ const ChatWidgetFooter = () => {
return (
<SwapColors>
<Paper square>
<Gutters>
{references.map(({ uri, title }) => (
<ReferencesListSmallItem uri={uri}>{title}</ReferencesListSmallItem>
<Gutters sx={{ '.MuiSvgIcon-root': { fontSize: gutters() } }}>
{references.map(({ uri, title, icon: iconName }) => (
<ReferencesListSmallItem uri={uri} iconComponent={Icons[iconName]}>
{title}
</ReferencesListSmallItem>
))}
</Gutters>
</Paper>
Expand Down
6 changes: 4 additions & 2 deletions src/main/guidance/chatWidget/ChatWidgetHelpDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Box, DialogProps, Typography } from '@mui/material';
import { gutters } from '../../../core/ui/grid/utils';
import { InfoOutlined } from '@mui/icons-material';
import Gutters from '../../../core/ui/grid/Gutters';
import { Text } from '../../../core/ui/typography';
import { useTranslation } from 'react-i18next';
import WrapperMarkdown from '../../../core/ui/markdown/WrapperMarkdown';

interface ChatWidgetHelpDialogProps extends DialogProps {
onClose?: () => void;
Expand All @@ -28,7 +28,9 @@ const ChatWidgetHelpDialog = ({ onClose, ...props }: ChatWidgetHelpDialogProps)
onClose={onClose}
/>
<Gutters paddingTop={0}>
<Text>{t('chatbot.infoDialog.content')}</Text>
<WrapperMarkdown caption disableParagraphPadding>
{t('chatbot.infoDialog.content')}
</WrapperMarkdown>
</Gutters>
</DialogWithGrid>
);
Expand Down
16 changes: 15 additions & 1 deletion src/main/guidance/chatWidget/ChatWidgetStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const ChatWidgetStyles = forwardRef<HTMLDivElement, BoxProps>((props, ref) => (
maxHeight: '-webkit-fill-available',
},
'.rcw-conversation-container': {
display: 'flex',
flexDirection: 'column',
marginBottom: gutters(0.5),
overflow: 'hidden',
minWidth: 0,
Expand Down Expand Up @@ -64,7 +66,19 @@ const ChatWidgetStyles = forwardRef<HTMLDivElement, BoxProps>((props, ref) => (
...background,
zIndex: 1, // Otherwise the custom header makes it unclickable
top: theme.spacing(1.5),
right: theme.spacing(0.5),
right: theme.spacing(1),
display: 'block',
border: 0,
position: 'absolute',
width: theme.spacing(3),
paddingX: 0,
cursor: 'pointer',
background: 'transparent',
'.rcw-close': {
padding: 0.2,
width: 20,
height: 20,
},
},
'.rcw-client .rcw-message-text': {
...background,
Expand Down
10 changes: 0 additions & 10 deletions src/main/guidance/chatWidget/ChatWidgetSubtitle.tsx

This file was deleted.

9 changes: 3 additions & 6 deletions src/main/guidance/chatWidget/ChatWidgetTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ import { InfoOutlined } from '@mui/icons-material';

interface ChatWidgetTitleProps {
onClickInfo?: () => void;
mobile?: boolean;
}

const ChatWidgetTitle = ({ onClickInfo, mobile = false }: ChatWidgetTitleProps) => {
const ChatWidgetTitle = ({ onClickInfo }: ChatWidgetTitleProps) => {
const { t } = useTranslation();

const infoButtonPosition = mobile ? 'left' : 'right';

return (
<Box display="flex" justifyContent="center" alignItems="center" position="relative" height={gutters(2.5)}>
<Box paddingTop={1}>
<Box>
<PageTitle position="relative">
{t('chatbot.title')}
<Caption
Expand All @@ -37,7 +34,7 @@ const ChatWidgetTitle = ({ onClickInfo, mobile = false }: ChatWidgetTitleProps)
<IconButton
size="small"
color="primary"
sx={{ position: 'absolute', top: 0, [infoButtonPosition]: 0 }}
sx={{ position: 'absolute', top: 0, right: gutters(1.5) }}
onClick={onClickInfo}
aria-label={t('common.help')}
>
Expand Down

0 comments on commit 282d74d

Please sign in to comment.