mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-08 23:20:46 +00:00
Merge pull request #8148 from overleaf/ta-pr-dictionary-style
Polish Dictionary Modal UI GitOrigin-RevId: 48aceb56c84a218380c619ecc5cd527f5062d3c4
This commit is contained in:
parent
5e08d5f505
commit
c66278cf89
6 changed files with 82 additions and 30 deletions
|
@ -120,7 +120,7 @@ aside#left-menu.full-size(
|
|||
if dictionaryEditorEnabled
|
||||
.form-controls(ng-controller="DictionaryModalController")
|
||||
label #{translate("dictionary")}
|
||||
button.btn.btn-default.btn-sm(ng-click="openModal()") #{translate("edit")}
|
||||
button.btn.btn-default.btn-xs(ng-click="openModal()") #{translate("edit")}
|
||||
|
||||
dictionary-modal(
|
||||
handle-hide="handleHide"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback } from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Alert, Button, Modal } from 'react-bootstrap'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
|
@ -6,11 +6,14 @@ import Tooltip from '../../../shared/components/tooltip'
|
|||
import useAsync from '../../../shared/hooks/use-async'
|
||||
import { postJSON } from '../../../infrastructure/fetch-json'
|
||||
import ignoredWords from '../ignored-words'
|
||||
import BetaBadge from '../../../shared/components/beta-badge'
|
||||
|
||||
type DictionaryModalContentProps = {
|
||||
handleHide: () => void
|
||||
}
|
||||
|
||||
const wordsSortFunction = (a, b) => a.localeCompare(b)
|
||||
|
||||
export default function DictionaryModalContent({
|
||||
handleHide,
|
||||
}: DictionaryModalContentProps) {
|
||||
|
@ -32,10 +35,31 @@ export default function DictionaryModalContent({
|
|||
[runAsync]
|
||||
)
|
||||
|
||||
const betaBadgeTooltipProps = useMemo(() => {
|
||||
return {
|
||||
id: 'dictionary-modal-tooltip',
|
||||
placement: 'bottom',
|
||||
className: 'tooltip-wide',
|
||||
text: (
|
||||
<>
|
||||
We are beta testing the dictionary manager.
|
||||
<br />
|
||||
Click to give feedback
|
||||
</>
|
||||
),
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>{t('edit_dictionary')}</Modal.Title>
|
||||
<Modal.Title>
|
||||
{t('edit_dictionary')}{' '}
|
||||
<BetaBadge
|
||||
tooltip={betaBadgeTooltipProps}
|
||||
url="https://forms.gle/8cLBEW6HU9mDKBPX9"
|
||||
/>
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
|
@ -44,26 +68,30 @@ export default function DictionaryModalContent({
|
|||
) : null}
|
||||
|
||||
{ignoredWords.learnedWords?.size > 0 ? (
|
||||
<ul className="list-unstyled">
|
||||
{[...ignoredWords.learnedWords].sort().map(learnedWord => (
|
||||
<li key={learnedWord}>
|
||||
<Tooltip
|
||||
id={`tooltip-remove-learned-word-${learnedWord}`}
|
||||
description={t('edit_dictionary_remove')}
|
||||
>
|
||||
<Button
|
||||
className="btn-link action-btn"
|
||||
onClick={() => handleRemove(learnedWord)}
|
||||
<ul className="list-unstyled dictionary-entries-list">
|
||||
{[...ignoredWords.learnedWords]
|
||||
.sort(wordsSortFunction)
|
||||
.map(learnedWord => (
|
||||
<li key={learnedWord} className="dictionary-entry">
|
||||
<span className="dictionary-entry-name">{learnedWord}</span>
|
||||
<Tooltip
|
||||
id={`tooltip-remove-learned-word-${learnedWord}`}
|
||||
description={t('edit_dictionary_remove')}
|
||||
overlayProps={{ delay: 0 }}
|
||||
>
|
||||
<Icon
|
||||
type="trash-o"
|
||||
accessibilityLabel={t('edit_dictionary_remove')}
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{learnedWord}
|
||||
</li>
|
||||
))}
|
||||
<Button
|
||||
bsStyle="danger"
|
||||
bsSize="xs"
|
||||
onClick={() => handleRemove(learnedWord)}
|
||||
>
|
||||
<Icon
|
||||
type="trash-o"
|
||||
accessibilityLabel={t('edit_dictionary_remove')}
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<i>{t('edit_dictionary_empty')}</i>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
@import './editor/publish-modal.less';
|
||||
@import './editor/outline.less';
|
||||
@import './editor/logs.less';
|
||||
@import './editor/dictionary.less';
|
||||
|
||||
@ui-layout-toggler-def-height: 50px;
|
||||
@ui-resizer-size: 7px;
|
||||
|
|
29
services/web/frontend/stylesheets/app/editor/dictionary.less
Normal file
29
services/web/frontend/stylesheets/app/editor/dictionary.less
Normal file
|
@ -0,0 +1,29 @@
|
|||
#dictionary-modal {
|
||||
.modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dictionary-entries-list {
|
||||
overflow-y: scroll;
|
||||
max-height: calc(100vh - 225px);
|
||||
margin: 0;
|
||||
padding: @padding-sm;
|
||||
}
|
||||
|
||||
.dictionary-entry {
|
||||
word-break: break-all;
|
||||
display: flex;
|
||||
padding: @padding-sm;
|
||||
border-bottom: solid 1px @modal-header-border-color;
|
||||
align-items: center;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dictionary-entry-name {
|
||||
flex-grow: 1;
|
||||
padding-right: @padding-xs;
|
||||
}
|
|
@ -126,9 +126,3 @@
|
|||
background-color: #999;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
#dictionary-modal {
|
||||
li {
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ describe('<DictionaryModalContent />', function () {
|
|||
|
||||
it('removes words', async function () {
|
||||
fetchMock.post('/spelling/unlearn', 200)
|
||||
setLearnedWords(['foo', 'bar'])
|
||||
setLearnedWords(['Foo', 'bar'])
|
||||
renderWithEditorContext(<DictionaryModal show handleHide={() => {}} />)
|
||||
screen.getByText('bar')
|
||||
const [firstButton] = screen.getAllByRole('button', {
|
||||
|
@ -41,7 +41,7 @@ describe('<DictionaryModalContent />', function () {
|
|||
})
|
||||
fireEvent.click(firstButton)
|
||||
expect(screen.queryByText('bar')).to.not.exist
|
||||
screen.getByText('foo')
|
||||
screen.getByText('Foo')
|
||||
})
|
||||
|
||||
it('handles errors', async function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue