main

mattermost/focalboard

Last updated at: 29/12/2023 09:42

viewHeaderSearch.tsx

TLDR

This file contains the ViewHeaderSearch component, which is a search field with a magnifying glass icon. It is used in the header of a view to search for cards. The component includes an editable input field that allows the user to enter and save search queries. The search field also supports keyboard shortcuts to focus on the input field.

Methods

No methods are defined in this file.

Classes

ViewHeaderSearch

The ViewHeaderSearch class is a React component that renders a search field in the header of a view. It includes the following features:

  • Uses Redux hooks (useAppSelector and useAppDispatch) to access the search text state from the store and dispatch actions to update it.
  • Uses React Router hook (useRouteMatch) to get the current view ID from the URL.
  • Uses React Intl hook (useIntl) to format the placeholder text for the search input.
  • Uses React Hotkeys Hook (useHotkeys) to bind keyboard shortcuts (ctrl+shift+f and cmd+shift+f) to focus on the search input field.
  • Includes a searchFieldRef to reference the input field and focus on it when a hotkey is triggered.
  • Uses the Editable component to provide an editable input field with placeholder text, event handlers to update the search value, and debounced dispatch of the search text to the store.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useState, useRef, useEffect, useMemo} from 'react'
import {useRouteMatch} from 'react-router-dom'
import {useIntl} from 'react-intl'
import {useHotkeys} from 'react-hotkeys-hook'
import {debounce} from 'lodash'

import CompassIcon from '../../widgets/icons/compassIcon'
import Editable from '../../widgets/editable'

import {useAppSelector, useAppDispatch} from '../../store/hooks'
import {getSearchText, setSearchText} from '../../store/searchText'

const ViewHeaderSearch = (): JSX.Element => {
    const searchText = useAppSelector<string>(getSearchText)
    const dispatch = useAppDispatch()
    const intl = useIntl()
    const match = useRouteMatch<{viewId?: string}>()

    const searchFieldRef = useRef<{focus(selectAll?: boolean): void}>(null)
    const [searchValue, setSearchValue] = useState(searchText)
    const [currentView, setCurrentView] = useState(match.params?.viewId)

    const dispatchSearchText = (value: string) => {
        dispatch(setSearchText(value))
    }

    const debouncedDispatchSearchText = useMemo(
        () => debounce(dispatchSearchText, 200), [])

    useEffect(() => {
        const viewId = match.params?.viewId
        if (viewId !== currentView) {
            setCurrentView(viewId)
            setSearchValue('')

            // Previously debounced calls to change the search text should be cancelled
            // to avoid resetting the search text.
            debouncedDispatchSearchText.cancel()
            dispatchSearchText('')
        }
    }, [match.url])

    useEffect(() => {
        return () => {
            debouncedDispatchSearchText.cancel()
        }
    }, [])

    useHotkeys('ctrl+shift+f,cmd+shift+f', () => {
        searchFieldRef.current?.focus(true)
    })

    return (
        <div className='board-search-field'>
            <CompassIcon
                icon='magnify'
                className='board-search-icon'
            />
            <Editable
                ref={searchFieldRef}
                value={searchValue}
                placeholderText={intl.formatMessage({id: 'ViewHeader.search-text', defaultMessage: 'Search cards'})}
                onChange={(value) => {
                    setSearchValue(value)
                    debouncedDispatchSearchText(value)
                }}
                onCancel={() => {
                    setSearchValue('')
                    debouncedDispatchSearchText('')
                }}
                onSave={() => {
                    debouncedDispatchSearchText(searchValue)
                }}
            />
        </div>
    )
}

export default ViewHeaderSearch