Add feedback link in spelling suggestion footer (#20867)

GitOrigin-RevId: 3bef428f810b88f56a76e3645cebcf22dd5ad9e3
This commit is contained in:
Alf Eaton 2024-10-08 09:25:49 +01:00 committed by Copybot
parent e99ae3a459
commit 139fde750a
6 changed files with 98 additions and 49 deletions

View file

@ -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)

View file

@ -8,19 +8,14 @@ import {
} from 'react' } from 'react'
import { SpellChecker, Word } from './spellchecker' import { SpellChecker, Word } from './spellchecker'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import SplitTestBadge from '@/shared/components/split-test-badge'
import getMeta from '@/utils/meta' import getMeta from '@/utils/meta'
import classnames from 'classnames' 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 { useFeatureFlag } from '@/shared/context/split-test-context'
import { sendMB } from '@/infrastructure/event-tracking' import { sendMB } from '@/infrastructure/event-tracking'
import SpellingSuggestionsFeedback from './spelling-suggestions-feedback'
const ITEMS_TO_SHOW = 8 const ITEMS_TO_SHOW = 8
// TODO: messaging below the spelling suggestions
const SHOW_FOOTER = false
// (index % length) that works for negative index // (index % length) that works for negative index
const wrapArrayIndex = (index: number, length: number) => const wrapArrayIndex = (index: number, length: number) =>
((index % length) + length) % length ((index % length) + length) % length
@ -76,6 +71,8 @@ export const SpellingSuggestions: FC<{
} }
}, [spellCheckLanguage]) }, [spellCheckLanguage])
const spellCheckClientEnabled = useFeatureFlag('spell-check-client')
return ( return (
<ul <ul
className={classnames('dropdown-menu', 'dropdown-menu-unpositioned', { className={classnames('dropdown-menu', 'dropdown-menu-unpositioned', {
@ -125,11 +122,11 @@ export const SpellingSuggestions: FC<{
handleLearnWord() handleLearnWord()
}} }}
/> />
{SHOW_FOOTER && language && ( {spellCheckClientEnabled && language?.dic && (
<> <>
<li className="divider" /> <li className="divider" />
<li> <li>
<Footer language={language} /> <SpellingSuggestionsFeedback />
</li> </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<{ const ListItem: FC<{
content: string content: string
selected: boolean selected: boolean

View file

@ -18,19 +18,7 @@ const BetaBadge: FC<{
url?: string url?: string
phase?: string phase?: string
}> = ({ tooltip, url = '/beta/participate', phase = 'beta' }) => { }> = ({ tooltip, url = '/beta/participate', phase = 'beta' }) => {
let badgeClass: 'info-badge' | 'alpha-badge' | 'beta-badge' const badgeClass = chooseBadgeClass(phase)
switch (phase) {
case 'release':
badgeClass = 'info-badge'
break
case 'alpha':
badgeClass = 'alpha-badge'
break
case 'beta':
default:
badgeClass = 'beta-badge'
}
return ( return (
<OLTooltip <OLTooltip
id={tooltip.id} 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 export default BetaBadge

View file

@ -1,13 +1,11 @@
import { createContext, FC, useContext, useMemo } from 'react' import { createContext, FC, useContext, useMemo } from 'react'
import getMeta from '../../utils/meta' import getMeta from '../../utils/meta'
import { SplitTestInfo } from '../../../../types/split-test'
type SplitTestVariants = Record<string, any>
type SplitTestInfo = Record<string, any>
export const SplitTestContext = createContext< export const SplitTestContext = createContext<
| { | {
splitTestVariants: SplitTestVariants splitTestVariants: Record<string, string>
splitTestInfo: SplitTestInfo splitTestInfo: Record<string, SplitTestInfo>
} }
| undefined | undefined
>(undefined) >(undefined)
@ -44,3 +42,15 @@ export function useFeatureFlag(name: string) {
const { splitTestVariants } = useSplitTestContext() const { splitTestVariants } = useSplitTestContext()
return splitTestVariants[name] === 'enabled' 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],
}
}

View file

@ -43,7 +43,11 @@ forEach(Object.keys(suggestions)).describe(
win.metaAttributesCache.set('ol-splitTestVariants', { win.metaAttributesCache.set('ol-splitTestVariants', {
'spell-check-client': 'enabled', '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-learnedWords', ['baz'])
win.metaAttributesCache.set( win.metaAttributesCache.set(
'ol-dictionariesRoot', 'ol-dictionariesRoot',

View file

@ -8,4 +8,8 @@ export type SplitTestInfo = {
rolloutPercent: number rolloutPercent: number
}[] }[]
hasOverride?: boolean hasOverride?: boolean
badgeInfo?: {
url?: string
tooltipText?: string
}
} }