mirror of
https://github.com/mattermost/focalboard.git
synced 2025-01-23 18:34:02 +02:00
All team users autocomplete new (#3016)
* WIP * Made search debounced * Lint fiX * Fixed tests * Calledn un-debounced version on first load
This commit is contained in:
parent
72eb7fa5a4
commit
859bc53cbb
@ -15,6 +15,8 @@ import {mockDOM, wrapDNDIntl, mockStateStore} from '../../testUtils'
|
||||
|
||||
import {Utils} from '../../utils'
|
||||
|
||||
import {TestBlockFactory} from "../../test/testBlockFactory"
|
||||
|
||||
import TextElement from './textElement'
|
||||
|
||||
jest.mock('../../utils')
|
||||
@ -41,6 +43,9 @@ describe('components/content/TextElement', () => {
|
||||
mockDOM()
|
||||
})
|
||||
|
||||
const board1 = TestBlockFactory.createBoard()
|
||||
board1.id = 'board-id-1'
|
||||
|
||||
const state = {
|
||||
users: {
|
||||
boardUsers: {
|
||||
@ -51,6 +56,12 @@ describe('components/content/TextElement', () => {
|
||||
5: {username: 'g'},
|
||||
},
|
||||
},
|
||||
boards: {
|
||||
current: 'board-id-1',
|
||||
boards: {
|
||||
[board1.id]: board1,
|
||||
}
|
||||
}
|
||||
}
|
||||
const store = mockStateStore([], state)
|
||||
|
||||
|
@ -65,6 +65,9 @@ describe('components/contentBlock', () => {
|
||||
addBlock: jest.fn(),
|
||||
})
|
||||
|
||||
const board1 = TestBlockFactory.createBoard()
|
||||
board1.id = 'board-id-1'
|
||||
|
||||
const state = {
|
||||
users: {
|
||||
boardUsers: {
|
||||
@ -75,6 +78,12 @@ describe('components/contentBlock', () => {
|
||||
5: {username: 'g'},
|
||||
},
|
||||
},
|
||||
boards: {
|
||||
current: 'board-id-1',
|
||||
boards: {
|
||||
[board1.id]: board1,
|
||||
}
|
||||
}
|
||||
}
|
||||
const store = mockStateStore([], state)
|
||||
|
||||
|
@ -7,6 +7,8 @@ import {Provider as ReduxProvider} from 'react-redux'
|
||||
|
||||
import {mockDOM, wrapDNDIntl, mockStateStore} from '../testUtils'
|
||||
|
||||
import {TestBlockFactory} from "../test/testBlockFactory"
|
||||
|
||||
import {MarkdownEditor} from './markdownEditor'
|
||||
|
||||
jest.mock('../utils')
|
||||
@ -16,6 +18,10 @@ jest.mock('draft-js/lib/generateRandomKey', () => () => '123')
|
||||
describe('components/markdownEditor', () => {
|
||||
beforeAll(mockDOM)
|
||||
beforeEach(jest.clearAllMocks)
|
||||
|
||||
const board1 = TestBlockFactory.createBoard()
|
||||
board1.id = 'board-id-1'
|
||||
|
||||
const state = {
|
||||
users: {
|
||||
boardUsers: {
|
||||
@ -26,6 +32,12 @@ describe('components/markdownEditor', () => {
|
||||
5: {username: 'g'},
|
||||
},
|
||||
},
|
||||
boards: {
|
||||
current: 'board-id-1',
|
||||
boards: {
|
||||
[board1.id]: board1,
|
||||
}
|
||||
}
|
||||
}
|
||||
const store = mockStateStore([], state)
|
||||
test('should match snapshot', async () => {
|
||||
|
@ -3,10 +3,7 @@
|
||||
import Editor from '@draft-js-plugins/editor'
|
||||
import createEmojiPlugin from '@draft-js-plugins/emoji'
|
||||
import '@draft-js-plugins/emoji/lib/plugin.css'
|
||||
import createMentionPlugin, {
|
||||
defaultSuggestionsFilter,
|
||||
MentionData,
|
||||
} from '@draft-js-plugins/mention'
|
||||
import createMentionPlugin from '@draft-js-plugins/mention'
|
||||
import '@draft-js-plugins/mention/lib/plugin.css'
|
||||
import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js'
|
||||
import React, {
|
||||
@ -15,6 +12,8 @@ import React, {
|
||||
useState,
|
||||
} from 'react'
|
||||
|
||||
import {debounce} from "lodash"
|
||||
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {IUser} from '../../user'
|
||||
import {getBoardUsersList} from '../../store/users'
|
||||
@ -22,10 +21,20 @@ import createLiveMarkdownPlugin from '../live-markdown-plugin/liveMarkdownPlugin
|
||||
|
||||
import './markdownEditorInput.scss'
|
||||
|
||||
import {BoardTypeOpen} from "../../blocks/board"
|
||||
import {getCurrentBoard} from "../../store/boards"
|
||||
import octoClient from "../../octoClient"
|
||||
|
||||
import Entry from './entryComponent/entryComponent'
|
||||
|
||||
const imageURLForUser = (window as any).Components?.imageURLForUser
|
||||
|
||||
type MentionUser = {
|
||||
name: string
|
||||
avatar: string
|
||||
is_bot: boolean
|
||||
}
|
||||
|
||||
type Props = {
|
||||
onChange?: (text: string) => void
|
||||
onFocus?: () => void
|
||||
@ -38,9 +47,38 @@ type Props = {
|
||||
const MarkdownEditorInput = (props: Props): ReactElement => {
|
||||
const {onChange, onFocus, onBlur, initialText, id, isEditing} = props
|
||||
const boardUsers = useAppSelector<IUser[]>(getBoardUsersList)
|
||||
const mentions: MentionData[] = useMemo(() => boardUsers.map((user) => ({name: user.username, avatar: `${imageURLForUser ? imageURLForUser(user.id) : ''}`, is_bot: user.is_bot})), [boardUsers])
|
||||
const board = useAppSelector(getCurrentBoard)
|
||||
const ref = useRef<Editor>(null)
|
||||
|
||||
const [suggestions, setSuggestions] = useState<Array<MentionUser>>([])
|
||||
|
||||
const loadSuggestions = async (term: string) => {
|
||||
let users: Array<IUser>
|
||||
|
||||
if (board && board.type === BoardTypeOpen) {
|
||||
users = await octoClient.searchTeamUsers(term)
|
||||
} else {
|
||||
users = boardUsers
|
||||
}
|
||||
|
||||
const mentions = users.map(
|
||||
(user) => ({
|
||||
name: user.username,
|
||||
avatar: `${imageURLForUser ? imageURLForUser(user.id) : ''}`,
|
||||
is_bot: user.is_bot}
|
||||
))
|
||||
setSuggestions(mentions)
|
||||
}
|
||||
|
||||
const debouncedLoadSuggestion = useMemo(() => debounce(loadSuggestions, 200), [])
|
||||
|
||||
useEffect(() => {
|
||||
// Get the ball rolling. Searching for empty string
|
||||
// returns first 10 users in alphabetical order.
|
||||
loadSuggestions('')
|
||||
}, [])
|
||||
|
||||
|
||||
const generateEditorState = (text?: string) => {
|
||||
const state = EditorState.createWithContent(ContentState.createFromText(text || ''))
|
||||
return EditorState.moveSelectionToEnd(state)
|
||||
@ -67,7 +105,6 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
|
||||
|
||||
const [isMentionPopoverOpen, setIsMentionPopoverOpen] = useState(false)
|
||||
const [isEmojiPopoverOpen, setIsEmojiPopoverOpen] = useState(false)
|
||||
const [suggestions, setSuggestions] = useState(mentions)
|
||||
|
||||
const {MentionSuggestions, plugins, EmojiSuggestions} = useMemo(() => {
|
||||
const mentionPlugin = createMentionPlugin({mentionPrefix: '@'})
|
||||
@ -144,8 +181,8 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
|
||||
}, [])
|
||||
|
||||
const onSearchChange = useCallback(({value}: { value: string }) => {
|
||||
setSuggestions(defaultSuggestionsFilter(value, mentions))
|
||||
}, [mentions])
|
||||
debouncedLoadSuggestion(value)
|
||||
}, [suggestions])
|
||||
|
||||
let className = 'MarkdownEditorInput'
|
||||
if (!isEditing) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user