Skip to content

Commit

Permalink
Merge pull request #707 from StampyAI/sundry-fixes
Browse files Browse the repository at this point in the history
Sundry fixes
  • Loading branch information
mruwnik authored Jun 8, 2024
2 parents d3215b9 + ad6a1c8 commit 04a5ecf
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 264 deletions.
21 changes: 5 additions & 16 deletions app/components/Article/Contents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useRef, useEffect} from 'react'
import useIsMobile from '~/hooks/isMobile'
import {questionUrl} from '~/routesMapper'
import type {Glossary, PageId, GlossaryEntry} from '~/server-utils/stampy'
import {togglePopup} from '../popups'

const footnoteHTML = (el: HTMLDivElement, e: HTMLAnchorElement): string | null => {
const id = e.getAttribute('href') || ''
Expand All @@ -19,19 +20,12 @@ const footnoteHTML = (el: HTMLDivElement, e: HTMLAnchorElement): string | null =
return elem.innerHTML
}

const scrollToElement = (e: HTMLElement, offset?: number) => {
const elementPosition = e.getBoundingClientRect().top + window.pageYOffset
const offsetPosition = elementPosition - (offset || 0)

window.scrollTo({top: offsetPosition, behavior: 'smooth'})
}

const addPopup = (e: HTMLElement, id: string, contents: string, mobile?: boolean): HTMLElement => {
const preexisting = document.getElementById(id)
if (preexisting) return preexisting

const popup = document.createElement('div')
popup.className = 'link-popup bordered small'
popup.className = 'link-popup bordered small background'
popup.innerHTML = contents
popup.id = id

Expand All @@ -43,14 +37,9 @@ const addPopup = (e: HTMLElement, id: string, contents: string, mobile?: boolean
popup.addEventListener('mouseover', () => popup.classList.add('shown'))
popup.addEventListener('mouseout', () => popup.classList.remove('shown'))
} else {
const togglePopup = (event: Event) => {
event.preventDefault()
popup.classList.toggle('shown')
document.body.classList.toggle('noscroll')
scrollToElement(e, 16)
}
popup.addEventListener('click', togglePopup)
e.addEventListener('click', togglePopup)
const toggle = () => popup.classList.toggle('shown')
popup.addEventListener('click', togglePopup(toggle, e))
e.addEventListener('click', togglePopup(toggle, e))
}

return popup
Expand Down
22 changes: 4 additions & 18 deletions app/components/Article/article.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ article .glossary-entry {

article .link-popup {
visibility: hidden;
opacity: 0;
z-index: 4;
position: absolute;
top: 0;
width: 512px;
}

Expand Down Expand Up @@ -218,25 +215,14 @@ article .banner h3 .title {
flex-direction: row;
flex-wrap: wrap;
}

article .link-popup {
width: 100%;
}
article .footer-comtainer > div:nth-child(-n + 2) {
flex: 1 1;
}
article {
margin: 0;
}

article .link-popup {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #ff000033;
overflow: scroll;
}
article .link-popup .footnote {
margin: auto;
background-color: white;
width: 80%;
}
}
1 change: 0 additions & 1 deletion app/components/ArticlesDropdown/dropdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
}

.articles-dropdown-container {
z-index: 100;
top: 80px;
position: absolute;
justify-content: space-between;
Expand Down
100 changes: 54 additions & 46 deletions app/components/ArticlesDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,50 @@ import Button from '~/components/Button'
import './dropdown.css'
import useIsMobile from '~/hooks/isMobile'

type LinkProps = {
to: string
text: string
pageid?: string
className?: string
onClick: () => void
}
const Link = ({to, text, pageid, className, onClick}: LinkProps) => (
<div className={'articles-dropdown-entry ' + (className || '')}>
<LinkElem to={to} onClick={onClick} state={{section: pageid}}>
{text}
</LinkElem>
</div>
)

type ArticlesSectionProps = {
category: Category
toc: TOCItem[]
className?: string
hide: () => void
}
const ArticlesSection = ({category, toc, className, hide}: ArticlesSectionProps) => (
<div className={className || ''}>
<div className="default-bold">{category} sections</div>
{toc
.filter((item) => item.category === category)
.map((item: TOCItem) => (
<Link
key={`${item.pageid}-${item.title}`}
to={questionUrl(item)}
text={item.title}
pageid={item.pageid}
onClick={hide}
/>
))}
</div>
)

export type ArticlesDropdownProps = {
toc: TOCItem[]
categories: Tag[]
fullWidth?: boolean
}
export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => {
export const ArticlesDropdown = ({toc, categories, fullWidth}: ArticlesDropdownProps) => {
// The dropdown works by using the onHover pseudoclass, so will only hide once
// the mouse leaves it. When using client side changes, the mouse doesn't leave
// it, so it's always shown (until the mouse is moved out, of course). To get around
Expand All @@ -22,63 +61,26 @@ export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => {
const hide = () => setHidden(true)
useEffect(() => setHidden(false), [hidden])
const mobile = useIsMobile()
const Link = ({
to,
text,
pageid,
className,
}: {
to: string
text: string
pageid?: string
className?: string
}) => (
<div className={'articles-dropdown-entry ' + (className || '')}>
<LinkElem to={to} onClick={hide} state={{section: pageid}}>
{text}
</LinkElem>
</div>
)

const ArticlesSection = ({
category,
toc,
className,
}: {
category: Category
toc: TOCItem[]
className?: string
}) => (
<div className={className || ''}>
<div className="default-bold">{category} sections</div>
{toc
.filter((item) => item.category === category)
.map((item: TOCItem) => (
<Link
key={`${item.pageid}-${item.title}`}
to={questionUrl(item)}
text={item.title}
pageid={item.pageid}
/>
))}
</div>
)

return hidden ? null : (
<div className="articles-dropdown-container bordered col-8">
<div className="col-5 toc">
<div
className={`articles-dropdown-container bordered ${fullWidth ? 'full-width' : 'col-8'} z-index-4`}
>
<div className={(fullWidth ? '' : 'col-5 ') + 'toc'}>
<ArticlesSection
category={INTRODUCTORY}
toc={toc}
className={mobile ? 'padding-bottom-40' : 'padding-bottom-32'}
hide={hide}
/>
<ArticlesSection
category={ADVANCED}
toc={toc}
className={mobile ? 'padding-bottom-40' : ''}
hide={hide}
/>
</div>
<div className="col-4">
<div className={fullWidth ? '' : 'col-4'}>
{/*sorted right side*/}
<div className="default-bold">Browse by category</div>

Expand All @@ -87,7 +89,13 @@ export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => {
?.sort(sortFuncs['by number of questions'])
.slice(0, 12)
.map((tag) => (
<Link key={tag.rowId} className="teal-500" to={tagUrl(tag)} text={tag.name} />
<Link
key={tag.rowId}
className="teal-500"
to={tagUrl(tag)}
text={tag.name}
onClick={hide}
/>
))}
</div>

Expand Down
1 change: 1 addition & 0 deletions app/components/Button/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
/* #### Composite button #### */
.composite-button {
cursor: pointer;
display: flex;
}

.composite-button > form .button,
Expand Down
6 changes: 4 additions & 2 deletions app/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ const Button = ({
(secondary && 'button-secondary') || 'button',
className,
tooltip && !secondary && 'tooltip',
secondary && active && 'active',
secondary && !active && !disabled && 'inactive',
]
.filter((i) => i)
.join(' ')
if (typeof action === 'string') {
return (
<Link
to={action}
className={classes + ' ' + (secondary && (active ? 'active' : disabled ? '' : 'inactive'))}
className={classes}
data-tooltip={tooltip}
onClick={(e) => {
if (disabled) {
Expand All @@ -49,7 +51,7 @@ const Button = ({
}
return (
<button
className={classes + ' ' + (secondary && (active ? 'active' : disabled ? '' : 'inactive'))}
className={classes}
onClick={action}
data-tooltip={tooltip}
disabled={disabled}
Expand Down
53 changes: 38 additions & 15 deletions app/components/Chatbot/ChatEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ComponentType, ReactNode} from 'react'
import {ComponentType, ReactNode, MouseEvent, useState, useRef} from 'react'
import {Link} from '@remix-run/react'
import MarkdownIt from 'markdown-it'
import Contents from '~/components/Article/Contents'
Expand All @@ -15,6 +15,8 @@ import StampyIcon from '~/components/icons-generated/Stampy'
import PersonInCircleIcon from '~/components/icons-generated/PersonInCircle'
import IconStampySmall from '~/components/icons-generated/StampySmall'
import QuestionMarkIcon from '~/components/icons-generated/QuestionMark'
import useIsMobile from '~/hooks/isMobile'
import {togglePopup} from '../popups'

const MAX_REFERENCES = 10

Expand Down Expand Up @@ -108,33 +110,53 @@ const ReferenceSummary = ({
}

const md = new MarkdownIt({html: true})
const ReferencePopup = (citation: Citation) => {
const ReferencePopup = (
citation: Citation & {className?: string; onClose?: (event: MouseEvent) => void}
) => {
const parsed = citation.text?.match(/^###.*?###\s+"""(.*?)"""$/ms)
if (!parsed) return undefined

return (
<div className="reference-contents bordered z-index-2">
<ReferenceSummary {...citation} titleClass="large-bold" />
<div className="grey padding-bottom-16 padding-top-32 xs">Referenced excerpt</div>
<div
className="default inner-html"
dangerouslySetInnerHTML={{
__html: md.render(parsed[1]),
}}
/>
<div
className={`reference-popup background z-index-2 ${citation.className || ''}`}
onClick={citation.onClose}
>
<div className="reference-contents bordered">
<ReferenceSummary {...citation} titleClass="large-bold" />
<div className="grey padding-bottom-16 padding-top-32 xs">Referenced excerpt</div>
<div
className="default inner-html"
dangerouslySetInnerHTML={{
__html: md.render(parsed[1]),
}}
/>
</div>
</div>
)
}

const ReferenceLink = (citation: Citation) => {
const ReferenceLink = (citation: Citation & {mobile?: boolean}) => {
const ref = useRef<HTMLAnchorElement>(null)
const [shown, setShown] = useState(false)
const clickHandler = !citation.mobile
? undefined
: togglePopup(() => setShown((current) => !current), ref.current || undefined)

const {id, index} = citation
if (!index || index > MAX_REFERENCES) return ''

return (
<span className="ref-container">
<Link id={`${id}-ref`} to={`#${id}`} className={`reference-link ref-${index}`}>
<Link
ref={ref}
id={`${id}-ref`}
to={`#${id}`}
className={`reference-link ref-${index}`}
onClick={clickHandler}
>
<span>{index}</span>
</Link>
<ReferencePopup {...citation} />
<ReferencePopup {...citation} className={shown ? 'shown' : 'hidden'} onClose={clickHandler} />
</span>
)
}
Expand All @@ -149,6 +171,7 @@ const Reference = (citation: Citation) => {
}

const ChatbotReply = ({question, phase, content, citationsMap}: AssistantEntry) => {
const mobile = useIsMobile()
const citations = [] as Citation[]
citationsMap?.forEach((v) => {
citations.push(v)
Expand Down Expand Up @@ -191,7 +214,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} {...ref} />
return ref && <ReferenceLink key={i} mobile={mobile} {...ref} />
} else if (chunk === '\n') {
return <br key={i} />
} else {
Expand Down
Loading

0 comments on commit 04a5ecf

Please sign in to comment.