import React, { KeyboardEvent } from 'react'; import Typography from '@material-ui/core/Typography'; import TextField from '@material-ui/core/TextField'; import MenuItem from '@material-ui/core/MenuItem'; import Container from '@material-ui/core/Container'; import Grid from '@material-ui/core/Grid'; import Pagination from '@material-ui/lab/Pagination'; import Box from '@material-ui/core/Box'; import useStyles from './SearchPage.style'; import { useSearch } from './utils/useSearch'; import { useFetch } from './utils/useFetch'; import { SearchParamSetter, useLocationSearch, useLocationSearchState } from './utils/routing'; import { SearchHit } from './SearchHit'; import { IndexedRule, IndexAggregates } from './types/IndexStore'; import { useHistory } from 'react-router-dom'; function correctResultsOrder(results: IndexedRule[], query: string): IndexedRule[] { const upperCaseQuery = query.toLocaleUpperCase(); const reorderedResults: IndexedRule[] = []; results.forEach(indexedRule => { if (indexedRule.all_keys.includes(upperCaseQuery)) { reorderedResults.unshift(indexedRule); } else { reorderedResults.push(indexedRule); } }); return reorderedResults; } export const SearchPage = () => { document.title = 'Search'; const classes = useStyles(); const pageSize = 20; const [query, setQuery] = useLocationSearchState('query', ''); const history = useHistory(); const [ruleType, setRuleType] = useLocationSearchState('types', 'ANY'); const allRuleTypes: Record = { 'BUG': 'Bug', 'CODE_SMELL': 'Code Smell', 'SECURITY_HOTSPOT': 'Security Hotspot', 'VULNERABILITY': 'Vulnerability' }; const [ruleTags, setRuleTags] = useLocationSearchState('tags', [], value => value ? value.split(',') : []); const [qualityProfiles, setQualityProfiles] = useLocationSearchState('qualityProfiles', [], value => value ? value.split(',') : []); const [ruleLang, setLanguage] = useLocationSearchState('lang', 'ANY'); const [pageNumber, setPageNumber] = useLocationSearchState('page', 1, parseInt); const {setLocationSearch} = useLocationSearch(); const {results, numberOfHits, error, loading} = useSearch(query, ruleType === 'ANY' ? null : ruleType, ruleLang === 'ANY' ? null : ruleLang, ruleTags, qualityProfiles, pageSize, pageNumber); const totalPages = numberOfHits ? Math.ceil(numberOfHits/pageSize) : 0; let allRuleTags:string[] = []; let allLangs:string[] = []; let allQualityProfiles = ['Sonar way', 'Sonar way recommended']; const aggregatesDataUrl = `${process.env.PUBLIC_URL}/rules/rule-index-aggregates.json`; const [aggregatesData, aggregatesDataError, aggregatesDataIsLoading] = useFetch(aggregatesDataUrl); if (aggregatesData && !aggregatesDataIsLoading && !aggregatesDataError) { allRuleTags = Object.keys(aggregatesData.tags).sort(); allLangs = Object.keys(aggregatesData.langs).sort(); allQualityProfiles = Object.keys(aggregatesData.qualityProfiles).sort(); } let resultsDisplay: string|JSX.Element[] = 'No rule found...'; if (loading) { resultsDisplay = 'Searching'; } else if (results.length > 0) { resultsDisplay = correctResultsOrder(results, query).map(indexedRule => ); } const paramSetters: Record> = { types: setRuleType, tags: setRuleTags, qualityProfiles: setQualityProfiles, lang:setLanguage, query: setQuery }; function handleUpdate(field: string) { return function(event: React.ChangeEvent) { if (pageNumber > 1) { const uriSearch: Record = { query: query, types: ruleType, tags: ruleTags, qualityProfiles: qualityProfiles, lang: ruleLang, page: 1 }; uriSearch[field] = event.target.value; setLocationSearch(uriSearch); } else { paramSetters[field](event.target.value, {push: false}); } } } function handleKeyup(event: KeyboardEvent) { if (event.key === 'Enter') { const query = (event.target as HTMLTextAreaElement).value; if (/^(S|RSPEC-?)?\d{3,}$/i.exec(query)) { if (0 < results.length) { history.push(correctResultsOrder(results, query)[0].id); } } else if (1 === results.length) { history.push(results[0].id); } } } return (
Any {Object.keys(allRuleTypes).map((ruleType) => ( {allRuleTypes[ruleType]} ))} { return selected.join(', '); } }} margin="normal" variant="outlined" label="Rule Tags" value={ruleTags} onChange={handleUpdate('tags')} data-testid="rule-tags" > {allRuleTags.map((ruleTag) => ( {ruleTag} ))} Any {allLangs.map((lang) => ( {lang} ))} { return selected.join(', '); } }} margin="normal" variant="outlined" label="Default Quality Profiles" value={qualityProfiles} onChange={handleUpdate('qualityProfiles')} data-testid="rule-default-quality-profile" > {allQualityProfiles.map((qualityProfile) => ( {qualityProfile} ))}
Number of rules found: {numberOfHits} {resultsDisplay} setPageNumber(value)} />
) }