Skip to content

Commit

Permalink
properly display popup content
Browse files Browse the repository at this point in the history
  • Loading branch information
mruwnik committed Jun 8, 2024
1 parent ad6a1c8 commit eec0673
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 19 deletions.
5 changes: 5 additions & 0 deletions app/assets/icons/exclamation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 11 additions & 7 deletions app/components/Article/Contents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const footnoteHTML = (el: HTMLDivElement, e: HTMLAnchorElement): string | null =

if (!footnote) return null

const elem = document.createElement('div')
elem.innerHTML = footnote.innerHTML
const elem = footnote.cloneNode(true) as Element

// remove the back link, as it's useless in the popup
if (elem?.firstElementChild?.lastChild)
elem.firstElementChild.removeChild(elem.firstElementChild.lastChild)
Array.from(elem.getElementsByClassName('footnote-backref')).forEach((e) => {
e.parentElement?.removeChild(e)
})

return elem.innerHTML
return elem.firstElementChild?.innerHTML || null
}

const addPopup = (e: HTMLElement, id: string, contents: string, mobile?: boolean): HTMLElement => {
Expand Down Expand Up @@ -81,6 +81,10 @@ const glossaryInjecter = (pageid: string, glossary: Glossary) => {
}

const insertGlossary = (pageid: string, glossary: Glossary) => {
// Generate a random ID for these glossary items. This is needed when mulitple articles are displayed -
// gloassary items should be only displayed once per article, but this is checked by popup id, so if
// there are 2 articles that have the same glossary item, then only the first articles popups would work
const randomId = Math.floor(1000 + Math.random() * 9000).toString()
const injecter = glossaryInjecter(pageid, glossary)

return (textNode: Node) => {
Expand Down Expand Up @@ -129,11 +133,11 @@ const insertGlossary = (pageid: string, glossary: Glossary) => {
const image = entry.image && `<img src="${entry.image}"/>`
addPopup(
e as HTMLSpanElement,
`glossary-${entry.term}`,
`glossary-${entry.term}-${randomId}`,
`<div class="glossary-popup flex-container black small">
<div class="contents ${image ? '' : 'full-width'}">
<div class="small-bold">${entry.term}</div>
<div class="defintion small">${entry.contents}</div>
<div class="definition small">${entry.contents}</div>
${link || ''}
</div>
${image || ''}
Expand Down
2 changes: 1 addition & 1 deletion app/components/Article/article.css
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ article .contents a.button {
article .link-popup .glossary-popup > .contents {
padding: var(--spacing-24) var(--spacing-40) var(--spacing-24);
}
article .defintion {
article .definition {
height: 140px;
display: -webkit-box;
/* These are webkit specific things, so might not work in all browsers (firefox handles them fine) */
Expand Down
21 changes: 16 additions & 5 deletions app/components/Chatbot/ChatEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,17 @@ const Reference = (citation: Citation) => {
)
}

const ChatbotReply = ({question, phase, content, citationsMap}: AssistantEntry) => {
const ChatbotReply = ({
question,
phase,
content,
citationsMap,
no,
}: AssistantEntry & {no: number}) => {
const mobile = useIsMobile()
const citations = [] as Citation[]
citationsMap?.forEach((v) => {
citations.push(v)
citations.push({...v, id: `${v.id}-${no}`})
})
citations.sort((a, b) => a.index - b.index)
const phaseMessageClass = 'phase-message large-reading'
Expand Down Expand Up @@ -214,7 +220,7 @@ const ChatbotReply = ({question, phase, content, citationsMap}: AssistantEntry)
if (chunk?.match(/(\[\d+\])/)) {
const refId = chunk.slice(1, chunk.length - 1)
const ref = citationsMap?.get(refId)
return ref && <ReferenceLink key={i} mobile={mobile} {...ref} />
return ref && <ReferenceLink key={i} mobile={mobile} {...ref} id={`${ref.id}-${no}`} />
} else if (chunk === '\n') {
return <br key={i} />
} else {
Expand Down Expand Up @@ -251,18 +257,23 @@ const ChatbotReply = ({question, phase, content, citationsMap}: AssistantEntry)
)
}

const StampyArticle = ({pageid, content, title}: StampyEntry) => {
const StampyArticle = ({pageid, content, title, no}: StampyEntry & {no: number}) => {
const glossary = useGlossary()
const hint = `This response is pulled from our article "${title}" which was written by members of AISafety.info`

const uniqueReferences = (content: string, idFinder: string) =>
content
.replaceAll(new RegExp(`id="(${idFinder})"`, 'g'), `id="$1-${no}"`)
.replaceAll(new RegExp(`href="#(${idFinder})"`, 'g'), `href="#$1-${no}"`)

return (
<div>
<Title title="Stampy" Icon={StampyIcon} answerType="human" hint={hint} />
<div className="answer">
<article className="stampy">
<Contents
pageid={pageid || ''}
html={content || 'Loading...'}
html={uniqueReferences(content || 'Loading...', 'fn\\d+-.*?')}
glossary={glossary || {}}
/>
</article>
Expand Down
4 changes: 4 additions & 0 deletions app/components/Chatbot/chat_entry.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,7 @@ article.stampy {
visibility: visible;
transition-delay: 0s;
}

.chat-entry article {
min-height: inherit;
}
15 changes: 10 additions & 5 deletions app/components/Chatbot/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {questionUrl} from '~/routesMapper'
import {Question} from '~/server-utils/stampy'
import {useSearch} from '~/hooks/useSearch'
import Input from '~/components/Input'
import {Exclamation} from '../icons-generated'

// to be replaced with actual pool questions
const poolQuestions = [
Expand Down Expand Up @@ -98,7 +99,7 @@ const QuestionInput = ({
<p className="default">{results[0].title}</p>
</Button>
) : undefined}
<div className="flex-container">
<div className="relative">
<Input
placeholder={placeholder}
className="large full-width shadowed"
Expand All @@ -115,6 +116,10 @@ const QuestionInput = ({
<SendIcon className="send pointer" onClick={() => handleAsk(question)} />
</div>
{fixed && <div className="white-space"></div>}

<div className="mobile-only grey padding-top-8">
<Exclamation /> <span>Stampy can be inaccurate. Always verify its sources.</span>
</div>
</div>
)
}
Expand Down Expand Up @@ -340,7 +345,7 @@ export const Chatbot = ({question, questions, settings}: ChatbotProps) => {
<SplashScreen questions={questions} onSelection={showArticleByID} />
) : undefined}
{history.map((item, i) => (
<ChatEntry key={`chat-entry-${i}`} {...item} />
<ChatEntry key={`chat-entry-${i}`} {...item} no={i} />
))}

<div className="padding-bottom-128">
Expand All @@ -360,9 +365,9 @@ export const Chatbot = ({question, questions, settings}: ChatbotProps) => {
fixed
/>

<div className={'warning-floating'}>
<p className={'xs'}>
<span className={'red xs-bold'}>Caution! </span>
<div className="desktop-only warning-floating">
<p className="xs">
<span className="red xs-bold">Caution! </span>
This is an early prototype. Don’t automatically trust what it says, and make sure to
follow its sources.
</p>
Expand Down
16 changes: 16 additions & 0 deletions app/components/icons-generated/Exclamation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type {SVGProps} from 'react'
const SvgExclamation = (props: SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" width={16} height={16} fill="none" {...props}>
<path
fill="#D40000"
d="M8.5 11a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0M7.5 5v4a.5.5 0 0 0 1 0V5a.5.5 0 0 0-1 0"
/>
<path
fill="#D40000"
fillRule="evenodd"
d="M8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12m0-1A5 5 0 1 0 8 3a5 5 0 0 0 0 10"
clipRule="evenodd"
/>
</svg>
)
export default SvgExclamation
1 change: 1 addition & 0 deletions app/components/icons-generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export {default as EclipseIndividual} from './EclipseIndividual'
export {default as EclipseTeam} from './EclipseTeam'
export {default as Edit} from './Edit'
export {default as Ellipsis} from './Ellipsis'
export {default as Exclamation} from './Exclamation'
export {default as Flag} from './Flag'
export {default as Followup} from './Followup'
export {default as GetInvolvedMobile} from './GetInvolvedMobile'
Expand Down
2 changes: 1 addition & 1 deletion app/hooks/useChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type Citation = {
id?: string
}

export type Entry = UserEntry | AssistantEntry | ErrorMessage | StampyEntry
export type Entry = (UserEntry | AssistantEntry | ErrorMessage | StampyEntry) & {no?: number}
export type ChatPhase =
| 'started'
| 'semantic'
Expand Down

0 comments on commit eec0673

Please sign in to comment.