Skip to content

Commit

Permalink
feat(webchat): added bot info page to webchat (#537)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelmass committed Sep 14, 2022
1 parent f467a13 commit bff1b2f
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 62 deletions.
4 changes: 2 additions & 2 deletions packages/webchat/src/components/common/Avatar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const Avatar = ({ name, avatarUrl, height, width }: AvatarProps) => {
export default Avatar

export interface AvatarProps {
name: string
avatarUrl: string
name?: string
avatarUrl?: string
height: number
width: number
}
134 changes: 76 additions & 58 deletions packages/webchat/src/components/common/BotInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import classnames from 'classnames'
import { inject, observer } from 'mobx-react'
import React, { Fragment } from 'react'
import { FormattedMessage, WrappedComponentProps, injectIntl } from 'react-intl'
import { BotInfo } from '../../..'

import EmailIcon from '../../../icons/Email'
import PhoneIcon from '../../../icons/Phone'
Expand All @@ -12,12 +11,9 @@ import { renderUnsafeHTML } from '../../../utils'

import Avatar from '../Avatar'

const CoverPicture = ({ botInfo }: { botInfo?: BotInfo }) => (
const CoverPicture = ({ coverPictureUrl }: { coverPictureUrl: string }) => (
<div className={'bpw-botinfo-cover-picture-wrapper'}>
<img
className={'bpw-botinfo-cover-picture'}
src={botInfo?.details.coverPictureUrl || `https://via.placeholder.com/400x175?text=${botInfo?.name || ''}`}
/>
<img className={'bpw-botinfo-cover-picture'} src={coverPictureUrl} />
</div>
)

Expand All @@ -30,7 +26,6 @@ class BotInfoPage extends React.Component<BotInfoProps> {

renderDescription(text: string) {
const html = renderUnsafeHTML(text, this.props.escapeHTML!)

return <div className={'bpw-botinfo-description'} dangerouslySetInnerHTML={{ __html: html }} />
}

Expand All @@ -40,7 +35,18 @@ class BotInfoPage extends React.Component<BotInfoProps> {
}

render() {
const { botInfo, botName, avatarUrl } = this.props
const {
botName,
avatarUrl,
coverPictureUrl,
description,
phoneNumber,
website,
emailAddress,
termsConditions,
privacyPolicy,
botInfo
} = this.props

const onDismiss = this.props.isConversationStarted ? this.props.toggleBotInfo : this.props.startConversation
return (
Expand All @@ -51,67 +57,65 @@ class BotInfoPage extends React.Component<BotInfoProps> {
'bpw-rtl': this.props.rtl
})}
>
<CoverPicture botInfo={botInfo} />
{coverPictureUrl ? <CoverPicture coverPictureUrl={coverPictureUrl} /> : <div style={{ height: '42px' }} />}
<div className={'bpw-botinfo-summary'}>
<Avatar name={botName!} avatarUrl={avatarUrl!} height={64} width={64} />
<h3>{botName}</h3>
{this.renderDescription(botInfo!.description)}
<Avatar name={botName} avatarUrl={avatarUrl} height={64} width={64} />
<h3 style={{ marginBottom: '10px' }}>{botName}</h3>
{description && this.renderDescription(description)}
</div>
{botInfo!.details && (
<React.Fragment>
<div className={'bpw-botinfo-links'}>
{botInfo!.details.phoneNumber && (
<div className={'bpw-botinfo-link'}>
<i>
<PhoneIcon />
</i>
<a target={'_blank'} href={`tel:${botInfo!.details.phoneNumber}`}>
{botInfo!.details.phoneNumber}
</a>
</div>
)}
{botInfo!.details.website && (
<div className={'bpw-botinfo-link'}>
<i>
<WebsiteIcon />
</i>
<a target={'_blank'} href={botInfo!.details.website}>
{botInfo!.details.website}
</a>
</div>
)}
{botInfo!.details.emailAddress && (
<div className={'bpw-botinfo-link'}>
<i>
<EmailIcon />
</i>
<a target={'_blank'} href={`mailto:${botInfo!.details.emailAddress}`}>
{botInfo!.details.emailAddress}
</a>
</div>
)}
</div>
{botInfo!.details.termsConditions && (
<div className={'bpw-botinfo-terms'}>
<a target={'_blank'} href={botInfo!.details.termsConditions}>
<FormattedMessage id={'botInfo.termsAndConditions'} />
<React.Fragment>
<div className={'bpw-botinfo-links'}>
{phoneNumber && (
<div className={'bpw-botinfo-link'}>
<i>
<PhoneIcon />
</i>
<a target={'_blank'} rel="noopener noreferrer" href={`tel:${phoneNumber}`}>
{phoneNumber}
</a>
</div>
)}
{botInfo!.details.privacyPolicy && (
<div className={'bpw-botinfo-terms'}>
<a target={'_blank'} href={botInfo!.details.privacyPolicy}>
<FormattedMessage id={'botInfo.privacyPolicy'} />
{website && (
<div className={'bpw-botinfo-link'}>
<i>
<WebsiteIcon />
</i>
<a target={'_blank'} rel="noopener noreferrer" href={website}>
{website}
</a>
</div>
)}
</React.Fragment>
)}
{botInfo!.languages.length > 1 && (
{emailAddress && (
<div className={'bpw-botinfo-link'}>
<i>
<EmailIcon />
</i>
<a target={'_blank'} rel="noopener noreferrer" href={`mailto:${emailAddress}`}>
{emailAddress}
</a>
</div>
)}
</div>
{termsConditions && (
<div className={'bpw-botinfo-terms'}>
<a target={'_blank'} rel="noopener noreferrer" href={termsConditions}>
<FormattedMessage id={'botInfo.termsAndConditions'} />
</a>
</div>
)}
{privacyPolicy && (
<div className={'bpw-botinfo-terms'}>
<a target={'_blank'} rel="noopener noreferrer" href={privacyPolicy}>
<FormattedMessage id={'botInfo.privacyPolicy'} />
</a>
</div>
)}
</React.Fragment>
{botInfo?.languages && botInfo.languages.length > 1 && (
<div className={'bpw-botinfo-preferred-language'}>
<FormattedMessage id={'botInfo.preferredLanguage'} />
<select value={this.props.preferredLanguage} onChange={this.changeLanguage}>
{botInfo!.languages.map((lang) => (
{botInfo.languages.map((lang) => (
<option key={lang} value={lang}>
{lang.toUpperCase()}
</option>
Expand All @@ -138,6 +142,13 @@ class BotInfoPage extends React.Component<BotInfoProps> {
}

export default inject(({ store }: { store: RootStore }) => ({
coverPictureUrl: store.coverPictureUrl,
description: store.description,
phoneNumber: store.phoneNumber,
website: store.website,
emailAddress: store.emailAddress,
termsConditions: store.termsConditions,
privacyPolicy: store.privacyPolicy,
botName: store.botName,
botInfo: store.botInfo,
avatarUrl: store.botAvatarUrl,
Expand All @@ -153,6 +164,13 @@ export default inject(({ store }: { store: RootStore }) => ({
type BotInfoProps = WrappedComponentProps &
Pick<
StoreDef,
| 'coverPictureUrl'
| 'description'
| 'phoneNumber'
| 'website'
| 'emailAddress'
| 'termsConditions'
| 'privacyPolicy'
| 'botInfo'
| 'botName'
| 'avatarUrl'
Expand Down
28 changes: 28 additions & 0 deletions packages/webchat/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ class RootStore {
return this.botInfo?.details?.avatarUrl || this.config?.avatarUrl || undefined
}

get coverPictureUrl() {
return this.botInfo?.details?.coverPictureUrl ?? this.config?.coverPictureUrl
}

get description() {
return this.config?.botConversationDescription
}

get website() {
return this.botInfo?.details?.website ?? this.config?.website
}

get phoneNumber() {
return this.botInfo?.details?.phoneNumber ?? this.config?.phoneNumber
}

get termsConditions() {
return this.botInfo?.details?.termsConditions ?? this.config?.termsConditions
}

get privacyPolicy() {
return this.botInfo?.details?.privacyPolicy ?? this.config?.privacyPolicy
}

get emailAddress() {
return this.botInfo?.details?.emailAddress ?? this.config?.emailAddress
}

@computed
get rtl(): boolean {
return isRTLLocale(this.preferredLanguage)
Expand Down
7 changes: 5 additions & 2 deletions packages/webchat/src/store/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ class ViewStore {

@computed
get showBotInfoButton() {
return !this.isConversationsDisplayed && this.rootStore.botInfo && this.rootStore.botInfo.showBotInfoPage
return (
!this.isConversationsDisplayed &&
(this.rootStore.botInfo?.showBotInfoPage || !!this.rootStore.config.showBotInfoPage)
)
}

@computed
Expand Down Expand Up @@ -106,7 +109,7 @@ class ViewStore {

@computed
get isBotInfoDisplayed(): boolean {
return this._showBotInfo && this.rootStore.botInfo && this.rootStore.botInfo.showBotInfoPage
return this._showBotInfo && (this.rootStore.botInfo?.showBotInfoPage || !!this.rootStore.config.showBotInfoPage)
}

/** Returns the active transition for the side panel, like fade in or out */
Expand Down
28 changes: 28 additions & 0 deletions packages/webchat/src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,34 @@ export interface Config {
* Allows setting a custom user id
*/
customUser?: UserCredentials
/**
* Displays the bot's website in the conversation page
*/
website?: string
/**
* Displays the bot's contact phone number in the conversation page
*/
phoneNumber?: string
/**
* Displays the bot's terms of service in the conversation page
*/
termsConditions?: string
/**
* Displays the bot's privacy policy in the conversation page
*/
privacyPolicy?: string
/**
* Displays the bot's email address in the conversation page
*/
emailAddress?: string
/**
* Displays the bot's cover picture in the conversation page
*/
coverPictureUrl?: string
/**
* Enables the bot's information page in the webchat
*/
showBotInfoPage?: boolean
}

export interface BotDetails {
Expand Down

0 comments on commit bff1b2f

Please sign in to comment.