• 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

95.74
/src/js/components/devices/widgets/issueselection.js
1
// Copyright 2021 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, useMemo, useState } from 'react';
15

16
// material ui
17
import { Checkbox, MenuItem, Select } from '@mui/material';
18

19
import { DEVICE_ISSUE_OPTIONS } from '../../../constants/deviceConstants';
20

21
const menuProps = {
9✔
22
  anchorOrigin: {
23
    vertical: 'bottom',
24
    horizontal: 'left'
25
  },
26
  transformOrigin: {
27
    vertical: 'top',
28
    horizontal: 'left'
29
  }
30
};
31
const groupOptions = (options = [], selection = []) => {
9!
32
  const things = options.reduce((accu, value) => {
3✔
33
    const { issueCategory, key } = DEVICE_ISSUE_OPTIONS[value.key];
7✔
34
    const nestedValue = { ...value, level: 0, checked: selection.includes(key) };
7✔
35
    if (issueCategory) {
7✔
36
      nestedValue.level = 1;
6✔
37
      let categoryItem = { ...DEVICE_ISSUE_OPTIONS[issueCategory], count: nestedValue.count, checked: nestedValue.checked };
6✔
38
      let existingItems = [];
6✔
39
      if (Array.isArray(accu[issueCategory])) {
6✔
40
        categoryItem = {
3✔
41
          ...accu[issueCategory][0],
42
          count: accu[issueCategory][0].count + nestedValue.count,
43
          checked: accu[issueCategory][0].checked && nestedValue.checked
4✔
44
        };
45
        existingItems = accu[issueCategory].slice(1);
3✔
46
      }
47
      accu[issueCategory] = [categoryItem, ...existingItems, nestedValue];
6✔
48
    } else {
49
      accu[key] = nestedValue;
1✔
50
    }
51
    return accu;
7✔
52
  }, {});
53
  return Object.values(things).flat();
3✔
54
};
55

56
const getSelectionDisplayValue = ({ selected = [], options = [] }) => {
9!
57
  let content = 'all';
22✔
58
  if (selected.length) {
22✔
59
    const { titles, sum } = selected.reduce(
18✔
60
      (accu, issue) => {
61
        accu.titles.push(DEVICE_ISSUE_OPTIONS[issue].title);
34✔
62
        accu.sum += options.find(option => option.key === issue)?.count || 0;
88✔
63
        return accu;
34✔
64
      },
65
      { titles: [], sum: 0 }
66
    );
67
    content = `${titles.join(', ')} (${sum})`;
18✔
68
  }
69
  return content;
22✔
70
};
71

72
const DeviceIssuesSelection = ({ classes, onChange, options, selection }) => {
9✔
73
  const [open, setOpen] = useState(false);
20✔
74

75
  const handleClose = () => setOpen(false);
20✔
76

77
  const handleOpen = e => {
20✔
78
    if (e && e.target.closest('input')?.hasOwnProperty('checked')) {
1!
79
      return;
×
80
    }
81
    setOpen(true);
1✔
82
  };
83

84
  // eslint-disable-next-line react-hooks/exhaustive-deps
85
  const groupedOptions = useMemo(() => groupOptions(options, selection), [options.join(''), selection.join('')]);
20✔
86

87
  const onSelectionChange = useCallback(
20✔
88
    ({ target: { value: newSelection } }, { props: { value: clickedItem } }) => {
89
      const issue = DEVICE_ISSUE_OPTIONS[clickedItem];
1✔
90
      let categoryItems = [];
1✔
91
      if (issue.isCategory) {
1!
92
        categoryItems = options.reduce(
1✔
93
          (collector, option) => (DEVICE_ISSUE_OPTIONS[option.key].issueCategory === clickedItem ? [...collector, option.key] : collector),
2!
94
          categoryItems
95
        );
96
      }
97

98
      let selectedOptions = newSelection;
1✔
99
      if (categoryItems.length && categoryItems.every(item => selection.includes(item))) {
1!
100
        selectedOptions = selectedOptions.filter(option => !(categoryItems.includes(option) || option === clickedItem));
×
101
      } else {
102
        selectedOptions = [...newSelection, ...categoryItems].filter(option => (issue.isCategory ? option !== clickedItem : true));
3!
103
      }
104
      onChange({ target: { value: [...new Set(selectedOptions)] } });
1✔
105
    },
106
    [onChange, options, selection]
107
  );
108

109
  return (
20✔
110
    <div className="flexbox center-aligned margin-left">
111
      <div>Show:</div>
112
      <Select
113
        className={classes.selection}
114
        disableUnderline
115
        displayEmpty
116
        MenuProps={menuProps}
117
        multiple
118
        open={open}
119
        onClose={handleClose}
120
        onOpen={handleOpen}
121
        onChange={onSelectionChange}
122
        renderValue={selected => getSelectionDisplayValue({ selected, options: groupedOptions })}
22✔
123
        value={selection}
124
      >
125
        {groupedOptions.map(({ checked, count, key, title, level = 0 }) => (
20✔
126
          <MenuItem key={key} value={key} size="small">
61✔
127
            <Checkbox checked={checked} style={{ marginLeft: 8 * (level + 1) }} />
128
            {title} ({count})
129
          </MenuItem>
130
        ))}
131
      </Select>
132
    </div>
133
  );
134
};
135

136
export default DeviceIssuesSelection;
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