rename GlobalSearchContext -> GlobalSearch, GlobalSearchProvider loads default search value from the query params, replace old HeaderSearchInput with the new one exported by GlobalSearch lib

This commit is contained in:
Dawid Wysokiński 2021-01-12 16:57:23 +01:00
parent c7d729ae19
commit e421102c6a
13 changed files with 44 additions and 32 deletions

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import { StringParam, useQueryParam, withDefault } from 'use-query-params';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { TWHELP, NAME } from '@config/app'; import { TWHELP, NAME } from '@config/app';
@ -20,7 +19,7 @@ import {
import { Input as InputIcon } from '@material-ui/icons'; import { Input as InputIcon } from '@material-ui/icons';
import Link from '@common/Link/Link'; import Link from '@common/Link/Link';
import VersionSelector from '@common/VersionSelector/VersionSelector'; import VersionSelector from '@common/VersionSelector/VersionSelector';
import SearchInput from './SearchInput'; import SearchInput from '@libs/GlobalSearch/SearchInput';
export interface Props { export interface Props {
appBarProps?: AppBarProps; appBarProps?: AppBarProps;
@ -30,7 +29,6 @@ export default function Header({ appBarProps = {} }: Props) {
const { t } = useTranslation(NAMESPACES.COMMON); const { t } = useTranslation(NAMESPACES.COMMON);
const location = useLocation(); const location = useLocation();
const classes = useStyles(); const classes = useStyles();
const [q] = useQueryParam('q', withDefault(StringParam, ''));
const versionSelector = ( const versionSelector = (
<div> <div>
@ -42,9 +40,7 @@ export default function Header({ appBarProps = {} }: Props) {
<Container> <Container>
<Toolbar disableGutters className={classes.toolbar}> <Toolbar disableGutters className={classes.toolbar}>
<form className={classes.form}> <form className={classes.form}>
<SearchInput <SearchInput />
defaultQ={location.pathname === ROUTES.SEARCH_PAGE ? q : ''}
/>
</form> </form>
{location.pathname !== ROUTES.INDEX_PAGE && ( {location.pathname !== ROUTES.INDEX_PAGE && (
<Link to={ROUTES.INDEX_PAGE}> <Link to={ROUTES.INDEX_PAGE}>

View File

@ -24,7 +24,7 @@ import {
Fireplace as FireplaceIcon, Fireplace as FireplaceIcon,
} from '@material-ui/icons'; } from '@material-ui/icons';
import DevNote from '@common/DevNote/DevNote'; import DevNote from '@common/DevNote/DevNote';
import SearchInput from '@common/MainLayout/components/Header/SearchInput'; import SearchInput from '@libs/GlobalSearch/SearchInput';
import Nav from './components/Nav/Nav'; import Nav from './components/Nav/Nav';
import ServerInfo from './components/ServerInfo/ServerInfo'; import ServerInfo from './components/ServerInfo/ServerInfo';

View File

@ -17,7 +17,7 @@ import {
import { Menu as MenuIcon, Input as InputIcon } from '@material-ui/icons'; import { Menu as MenuIcon, Input as InputIcon } from '@material-ui/icons';
import VersionSelector from '@common/VersionSelector/VersionSelector'; import VersionSelector from '@common/VersionSelector/VersionSelector';
import Link from '@common/Link/Link'; import Link from '@common/Link/Link';
import SearchInput from '@common/MainLayout/components/Header/SearchInput'; import SearchInput from '@libs/GlobalSearch/SearchInput';
export interface Props { export interface Props {
className?: string; className?: string;

View File

@ -7,6 +7,7 @@ import { ApolloProvider } from '@apollo/client';
import { BrowserRouter, Route } from 'react-router-dom'; import { BrowserRouter, Route } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { QueryParamProvider } from 'use-query-params'; import { QueryParamProvider } from 'use-query-params';
import GlobalSearchProvider from './libs/GlobalSearch/Provider';
import App from './features/App'; import App from './features/App';
import createTheme from './theme/createTheme'; import createTheme from './theme/createTheme';
import createGraphQLClient from './libs/graphql/createClient'; import createGraphQLClient from './libs/graphql/createClient';
@ -20,7 +21,9 @@ const jsx = (
<I18nextProvider i18n={initI18N()}> <I18nextProvider i18n={initI18N()}>
<ApolloProvider client={createGraphQLClient(API_URI)}> <ApolloProvider client={createGraphQLClient(API_URI)}>
<QueryParamProvider ReactRouterRoute={Route}> <QueryParamProvider ReactRouterRoute={Route}>
<App /> <GlobalSearchProvider>
<App />
</GlobalSearchProvider>
</QueryParamProvider> </QueryParamProvider>
</ApolloProvider> </ApolloProvider>
</I18nextProvider> </I18nextProvider>

View File

@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory, useLocation } from 'react-router-dom';
import { useQueryParam, StringParam, withDefault } from 'use-query-params';
import { SEARCH_PAGE } from '@config/routes'; import { SEARCH_PAGE } from '@config/routes';
import Context from './context'; import Context from './context';
@ -8,9 +9,13 @@ export interface Props {
children?: React.ReactNode; children?: React.ReactNode;
} }
function Provider({ children }: Props) { function Provider({ children, ...rest }: Props) {
const [q, setQ] = useState<string>(''); const [defaultQ] = useQueryParam('q', withDefault(StringParam, ''));
const history = useHistory(); const history = useHistory();
const location = useLocation();
const [q, setQ] = useState<string>(
location.pathname === SEARCH_PAGE ? defaultQ : ''
);
const href = SEARCH_PAGE + `?q=${encodeURIComponent(q)}`; const href = SEARCH_PAGE + `?q=${encodeURIComponent(q)}`;
const goToSearchPage = () => { const goToSearchPage = () => {

View File

@ -1,6 +1,6 @@
import React, { useState } from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import * as ROUTES from '@config/routes'; import useGlobalSearch from './useGlobalSearch';
import * as NAMESPACES from '@config/namespaces'; import * as NAMESPACES from '@config/namespaces';
import { InputAdornment, IconButton, TextFieldProps } from '@material-ui/core'; import { InputAdornment, IconButton, TextFieldProps } from '@material-ui/core';
@ -8,13 +8,9 @@ import { Search as SearchIcon } from '@material-ui/icons';
import SearchInput from '@common/Form/SearchInput'; import SearchInput from '@common/Form/SearchInput';
import Link from '@common/Link/Link'; import Link from '@common/Link/Link';
export type Props = TextFieldProps & { function CustomizedSearchInput(props: TextFieldProps) {
defaultQ?: string;
};
function HeaderSearchInput({ defaultQ = '', ...rest }: Props) {
const { t } = useTranslation(NAMESPACES.COMMON); const { t } = useTranslation(NAMESPACES.COMMON);
const [q, setQ] = useState<string>(defaultQ); const { q, setQ, href } = useGlobalSearch();
const trimmedQLength = q.trim().length; const trimmedQLength = q.trim().length;
const iconButton = ( const iconButton = (
<IconButton size="small" type="submit" disabled={trimmedQLength === 0}> <IconButton size="small" type="submit" disabled={trimmedQLength === 0}>
@ -26,9 +22,9 @@ function HeaderSearchInput({ defaultQ = '', ...rest }: Props) {
<SearchInput <SearchInput
fullWidth fullWidth
variant="outlined" variant="outlined"
placeholder={t<string>('mainLayout.header.search')} placeholder={t<string>('globalSearch.searchInput.placeholder')}
size="small" size="small"
{...rest} {...props}
value={q} value={q}
onChange={e => { onChange={e => {
setQ(e.target.value); setQ(e.target.value);
@ -36,13 +32,7 @@ function HeaderSearchInput({ defaultQ = '', ...rest }: Props) {
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
{trimmedQLength ? ( {trimmedQLength ? <Link to={href}>{iconButton}</Link> : iconButton}
<Link to={ROUTES.SEARCH_PAGE + `?q=${encodeURIComponent(q)}`}>
{iconButton}
</Link>
) : (
iconButton
)}
</InputAdornment> </InputAdornment>
), ),
}} }}
@ -51,4 +41,4 @@ function HeaderSearchInput({ defaultQ = '', ...rest }: Props) {
); );
} }
export default HeaderSearchInput; export default CustomizedSearchInput;

View File

@ -17,10 +17,14 @@ const translations = {
loading: 'Loading version...', loading: 'Loading version...',
}, },
devNote: `This website is still under development and some things may be broken.`, devNote: `This website is still under development and some things may be broken.`,
globalSearch: {
searchInput: {
placeholder: 'Search',
},
},
mainLayout: { mainLayout: {
header: { header: {
home: 'Home', home: 'Home',
search: 'Search',
}, },
}, },
}; };

View File

@ -17,10 +17,14 @@ const translations = {
loading: 'Ładowanie wersji...', loading: 'Ładowanie wersji...',
}, },
devNote: `Strona jest ciągle w procesie tworzenia i mogą występować błędy.`, devNote: `Strona jest ciągle w procesie tworzenia i mogą występować błędy.`,
globalSearch: {
searchInput: {
placeholder: 'Wyszukaj',
},
},
mainLayout: { mainLayout: {
header: { header: {
home: 'Strona główna', home: 'Strona główna',
search: 'Wyszukaj',
}, },
}, },
}; };

View File

@ -17,6 +17,11 @@ const translations = {
loading: 'Carregando a versão...', loading: 'Carregando a versão...',
}, },
devNote: `Este site ainda está em desenvolvimento e poder conter erros.`, devNote: `Este site ainda está em desenvolvimento e poder conter erros.`,
globalSearch: {
searchInput: {
placeholder: 'Pesquisa',
},
},
mainLayout: { mainLayout: {
header: { header: {
home: 'Início', home: 'Início',

View File

@ -17,6 +17,11 @@ const translations = {
loading: 'Carregando a versão...', loading: 'Carregando a versão...',
}, },
devNote: `Este site ainda está sendo desenvolvido e pode conter algum erro.`, devNote: `Este site ainda está sendo desenvolvido e pode conter algum erro.`,
globalSearch: {
searchInput: {
placeholder: 'Pesquisa',
},
},
mainLayout: { mainLayout: {
header: { header: {
home: 'Página inicial', home: 'Página inicial',