• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 1113439055

19 Dec 2023 09:01PM UTC coverage: 82.752% (-17.2%) from 99.964%
1113439055

Pull #4258

gitlab-ci

mender-test-bot
chore: Types update

Signed-off-by: Mender Test Bot <mender@northern.tech>
Pull Request #4258: chore: Types update

4326 of 6319 branches covered (0.0%)

8348 of 10088 relevant lines covered (82.75%)

189.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/js/components/common/search.js
1
// Copyright 2022 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import React, { useCallback, useEffect, useRef } from 'react';
15
import { Controller, FormProvider, useForm, useFormContext } from 'react-hook-form';
16

17
import { Search as SearchIcon } from '@mui/icons-material';
18
import { InputAdornment, TextField } from '@mui/material';
19
import { makeStyles } from 'tss-react/mui';
20

21
import { TIMEOUTS } from '../../constants/appConstants';
22
import { useDebounce } from '../../utils/debouncehook';
23
import Loader from './loader';
24

25
const useStyles = makeStyles()(() => ({
14✔
26
  root: {
27
    input: {
28
      fontSize: '13px'
29
    }
30
  }
31
}));
32

33
const endAdornment = (
34
  <InputAdornment position="end">
5✔
35
    <Loader show small style={{ marginTop: -10 }} />
36
  </InputAdornment>
37
);
38

39
const startAdornment = (
40
  <InputAdornment position="start">
5✔
41
    <SearchIcon color="disabled" fontSize="small" />
42
  </InputAdornment>
43
);
44

45
// due to search not working reliably for single letter searches, only start at 2
46
const MINIMUM_SEARCH_LENGTH = 2;
5✔
47

48
export const ControlledSearch = ({ isSearching, name = 'search', onSearch, placeholder = 'Search devices', style = {} }) => {
5✔
49
  const { classes } = useStyles();
445✔
50
  const { control, watch } = useFormContext();
445✔
51
  const inputRef = useRef();
445✔
52

53
  const searchValue = watch('search', '');
445✔
54

55
  const debouncedSearchTerm = useDebounce(searchValue, TIMEOUTS.debounceDefault);
445✔
56

57
  useEffect(() => {
445✔
58
    if (debouncedSearchTerm.length < MINIMUM_SEARCH_LENGTH) {
12!
59
      return;
12✔
60
    }
61
    onSearch(debouncedSearchTerm).then(() => inputRef.current.focus());
×
62
  }, [debouncedSearchTerm, onSearch]);
63

64
  const onTriggerSearch = useCallback(
445✔
65
    ({ key }) => {
66
      if (key === 'Enter' && (!debouncedSearchTerm || debouncedSearchTerm.length >= MINIMUM_SEARCH_LENGTH)) {
2!
67
        onSearch(debouncedSearchTerm).then(() => inputRef.current.focus());
×
68
      }
69
    },
70
    [debouncedSearchTerm, onSearch]
71
  );
72

73
  const adornments = isSearching ? { startAdornment, endAdornment } : { startAdornment };
445✔
74
  return (
445✔
75
    <Controller
76
      name={name}
77
      control={control}
78
      render={({ field }) => (
79
        <TextField
443✔
80
          className={classes.root}
81
          InputProps={adornments}
82
          onKeyPress={onTriggerSearch}
83
          placeholder={placeholder}
84
          inputRef={inputRef}
85
          size="small"
86
          style={style}
87
          {...field}
88
        />
89
      )}
90
    />
91
  );
92
};
93

94
ControlledSearch.displayName = 'ConnectedSearch';
5✔
95

96
const Search = props => {
5✔
97
  const { searchTerm, onSearch, trigger } = props;
393✔
98
  const methods = useForm({ mode: 'onChange', defaultValues: { search: searchTerm ?? '' } });
393!
99
  const { handleSubmit } = methods;
393✔
100
  return (
393✔
101
    <FormProvider {...methods}>
102
      <form noValidate onSubmit={handleSubmit(({ search }) => onSearch(search, !trigger))}>
×
103
        <ControlledSearch {...props} />
104
        <input className="hidden" type="submit" />
105
      </form>
106
    </FormProvider>
107
  );
108
};
109

110
export default Search;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc