mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add feedback link in spelling suggestion footer (#20867)
GitOrigin-RevId: 3bef428f810b88f56a76e3645cebcf22dd5ad9e3
This commit is contained in:
parent
e99ae3a459
commit
139fde750a
6 changed files with 98 additions and 49 deletions
|
@ -0,0 +1,56 @@
|
|||
import { FC, memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSplitTest } from '@/shared/context/split-test-context'
|
||||
import { chooseBadgeClass } from '@/shared/components/beta-badge'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import classnames from 'classnames'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
const SpellingSuggestionsFeedback: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { info } = useSplitTest('spell-check-client')
|
||||
|
||||
if (!info) {
|
||||
return null
|
||||
}
|
||||
|
||||
const { tooltipText, url } = info.badgeInfo ?? {}
|
||||
const badgeClass = chooseBadgeClass(info.phase)
|
||||
|
||||
return (
|
||||
<OLTooltip
|
||||
id="spell-check-client-tooltip"
|
||||
description={
|
||||
tooltipText || (
|
||||
<>
|
||||
We are testing an updated spellchecker.
|
||||
<br />
|
||||
Click to give feedback
|
||||
</>
|
||||
)
|
||||
}
|
||||
tooltipProps={{ className: 'split-test-badge-tooltip' }}
|
||||
overlayProps={{ placement: 'bottom', delay: 100 }}
|
||||
>
|
||||
<a
|
||||
href={url || '/beta/participate'}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<span className={classnames('badge', badgeClass)} />}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
type="info"
|
||||
className={classnames('align-middle', badgeClass)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<span className="mx-2">{t('give_feedback')}</span>
|
||||
</a>
|
||||
</OLTooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(SpellingSuggestionsFeedback)
|
|
@ -8,19 +8,14 @@ import {
|
|||
} from 'react'
|
||||
import { SpellChecker, Word } from './spellchecker'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SplitTestBadge from '@/shared/components/split-test-badge'
|
||||
import getMeta from '@/utils/meta'
|
||||
import classnames from 'classnames'
|
||||
import { SpellCheckLanguage } from '../../../../../../types/project-settings'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import SpellingSuggestionsFeedback from './spelling-suggestions-feedback'
|
||||
|
||||
const ITEMS_TO_SHOW = 8
|
||||
|
||||
// TODO: messaging below the spelling suggestions
|
||||
const SHOW_FOOTER = false
|
||||
|
||||
// (index % length) that works for negative index
|
||||
const wrapArrayIndex = (index: number, length: number) =>
|
||||
((index % length) + length) % length
|
||||
|
@ -76,6 +71,8 @@ export const SpellingSuggestions: FC<{
|
|||
}
|
||||
}, [spellCheckLanguage])
|
||||
|
||||
const spellCheckClientEnabled = useFeatureFlag('spell-check-client')
|
||||
|
||||
return (
|
||||
<ul
|
||||
className={classnames('dropdown-menu', 'dropdown-menu-unpositioned', {
|
||||
|
@ -125,11 +122,11 @@ export const SpellingSuggestions: FC<{
|
|||
handleLearnWord()
|
||||
}}
|
||||
/>
|
||||
{SHOW_FOOTER && language && (
|
||||
{spellCheckClientEnabled && language?.dic && (
|
||||
<>
|
||||
<li className="divider" />
|
||||
<li>
|
||||
<Footer language={language} />
|
||||
<SpellingSuggestionsFeedback />
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
|
@ -137,28 +134,6 @@ export const SpellingSuggestions: FC<{
|
|||
)
|
||||
}
|
||||
|
||||
const Footer: FC<{ language: SpellCheckLanguage }> = ({ language }) => {
|
||||
const spellCheckClientEnabled = useFeatureFlag('spell-check-client')
|
||||
|
||||
if (!spellCheckClientEnabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
return language.dic ? (
|
||||
<div>
|
||||
<SplitTestBadge
|
||||
splitTestName="spell-check-client"
|
||||
displayOnVariants={['enabled']}
|
||||
/>{' '}
|
||||
<small>{language?.name}</small>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Icon type="warning" fw /> <small>{language?.name}</small>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ListItem: FC<{
|
||||
content: string
|
||||
selected: boolean
|
||||
|
|
|
@ -18,19 +18,7 @@ const BetaBadge: FC<{
|
|||
url?: string
|
||||
phase?: string
|
||||
}> = ({ tooltip, url = '/beta/participate', phase = 'beta' }) => {
|
||||
let badgeClass: 'info-badge' | 'alpha-badge' | 'beta-badge'
|
||||
switch (phase) {
|
||||
case 'release':
|
||||
badgeClass = 'info-badge'
|
||||
break
|
||||
case 'alpha':
|
||||
badgeClass = 'alpha-badge'
|
||||
break
|
||||
case 'beta':
|
||||
default:
|
||||
badgeClass = 'beta-badge'
|
||||
}
|
||||
|
||||
const badgeClass = chooseBadgeClass(phase)
|
||||
return (
|
||||
<OLTooltip
|
||||
id={tooltip.id}
|
||||
|
@ -57,4 +45,16 @@ const BetaBadge: FC<{
|
|||
)
|
||||
}
|
||||
|
||||
export const chooseBadgeClass = (phase?: string) => {
|
||||
switch (phase) {
|
||||
case 'release':
|
||||
return 'info-badge'
|
||||
case 'alpha':
|
||||
return 'alpha-badge'
|
||||
case 'beta':
|
||||
default:
|
||||
return 'beta-badge'
|
||||
}
|
||||
}
|
||||
|
||||
export default BetaBadge
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import { createContext, FC, useContext, useMemo } from 'react'
|
||||
import getMeta from '../../utils/meta'
|
||||
|
||||
type SplitTestVariants = Record<string, any>
|
||||
type SplitTestInfo = Record<string, any>
|
||||
import { SplitTestInfo } from '../../../../types/split-test'
|
||||
|
||||
export const SplitTestContext = createContext<
|
||||
| {
|
||||
splitTestVariants: SplitTestVariants
|
||||
splitTestInfo: SplitTestInfo
|
||||
splitTestVariants: Record<string, string>
|
||||
splitTestInfo: Record<string, SplitTestInfo>
|
||||
}
|
||||
| undefined
|
||||
>(undefined)
|
||||
|
@ -44,3 +42,15 @@ export function useFeatureFlag(name: string) {
|
|||
const { splitTestVariants } = useSplitTestContext()
|
||||
return splitTestVariants[name] === 'enabled'
|
||||
}
|
||||
|
||||
export function useSplitTest(name: string): {
|
||||
variant: string | undefined
|
||||
info: SplitTestInfo | undefined
|
||||
} {
|
||||
const { splitTestVariants, splitTestInfo } = useSplitTestContext()
|
||||
|
||||
return {
|
||||
variant: splitTestVariants[name],
|
||||
info: splitTestInfo[name],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,11 @@ forEach(Object.keys(suggestions)).describe(
|
|||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'spell-check-client': 'enabled',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'spell-check-client': {
|
||||
phase: 'release',
|
||||
},
|
||||
})
|
||||
win.metaAttributesCache.set('ol-learnedWords', ['baz'])
|
||||
win.metaAttributesCache.set(
|
||||
'ol-dictionariesRoot',
|
||||
|
|
|
@ -8,4 +8,8 @@ export type SplitTestInfo = {
|
|||
rolloutPercent: number
|
||||
}[]
|
||||
hasOverride?: boolean
|
||||
badgeInfo?: {
|
||||
url?: string
|
||||
tooltipText?: string
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue