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

mendersoftware / gui / 1350829378

27 Jun 2024 01:46PM UTC coverage: 83.494% (-16.5%) from 99.965%
1350829378

Pull #4465

gitlab-ci

mzedel
chore: test fixes

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #4465: MEN-7169 - feat: added multi sorting capabilities to devices view

4506 of 6430 branches covered (70.08%)

81 of 100 new or added lines in 14 files covered. (81.0%)

1661 existing lines in 163 files now uncovered.

8574 of 10269 relevant lines covered (83.49%)

160.6 hits per line

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

56.76
/src/js/components/common/detailstable.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, { useEffect, useState } from 'react';
15

16
// material ui
17
import { Checkbox, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material';
18
import { makeStyles } from 'tss-react/mui';
19

20
import { SORTING_OPTIONS, SORT_DIRECTIONS, TIMEOUTS } from '../../constants/appConstants';
21
import { useDebounce } from '../../utils/debouncehook';
22
import SortIcon from './sorticon';
23

24
const useStyles = makeStyles()(() => ({
19✔
25
  header: {
26
    '.columnHeader': {
27
      display: 'table-cell'
28
    },
29
    '.columnHeader .sortIcon': {
30
      marginBottom: -6
31
    },
32
    '.nonSortable': { cursor: 'initial' }
33
  }
34
}));
35

36
const HeaderItem = ({ columnKey, hasMultiSort, extras, renderTitle, sortable, onSort, sortOptions, title }) => {
19✔
37
  const { direction, key: sortKey } = sortOptions.find(({ key: sortKey }) => columnKey === sortKey) ?? {};
335✔
38
  const [sortState, setSortState] = useState({ disabled: !sortKey, direction });
335✔
39
  const [resetDirection] = useState(hasMultiSort ? '' : SORT_DIRECTIONS[0]);
335!
40

41
  const debouncedSortState = useDebounce(sortState, TIMEOUTS.debounceShort);
335✔
42

43
  useEffect(() => {
335✔
44
    if (!onSort) {
83✔
45
      return;
63✔
46
    }
47
    onSort({ key: columnKey, direction: debouncedSortState.direction, disabled: debouncedSortState.disabled });
20✔
48
  }, [columnKey, debouncedSortState.direction, debouncedSortState.disabled, onSort]);
49

50
  const onSortClick = () => {
335✔
NEW
51
    if (!sortable) {
×
NEW
52
      return;
×
53
    }
NEW
54
    const nextDirectionIndex = SORT_DIRECTIONS.indexOf(sortState.direction) + 1;
×
NEW
55
    const direction = SORT_DIRECTIONS[nextDirectionIndex] ?? resetDirection;
×
NEW
56
    setSortState({ direction, disabled: !direction });
×
57
  };
58

59
  const sortDown = sortKey && direction === SORTING_OPTIONS.desc;
335✔
60

61
  return (
335✔
62
    <TableCell className={`columnHeader ${sortable ? '' : 'nonSortable'}`} onClick={onSortClick}>
335✔
63
      {renderTitle ? renderTitle(extras) : title}
335✔
64
      {sortable && <SortIcon columnKey={sortKey} disabled={sortState.disabled} sortDown={sortDown} />}
452✔
65
    </TableCell>
66
  );
67
};
68

69
export const DetailsTable = ({
19✔
70
  className = '',
63✔
71
  columns,
72
  hasMultiSort = false,
70✔
73
  items,
74
  onChangeSorting,
75
  onItemClick,
76
  sort = [],
32✔
77
  style = {},
70✔
78
  tableRef,
79
  onRowSelected,
80
  selectedRows = []
32✔
81
}) => {
82
  const { classes } = useStyles();
70✔
83

84
  const onRowSelection = selectedRow => {
70✔
UNCOV
85
    let updatedSelection = [...selectedRows];
×
UNCOV
86
    const selectedIndex = updatedSelection.indexOf(selectedRow);
×
UNCOV
87
    if (selectedIndex === -1) {
×
UNCOV
88
      updatedSelection.push(selectedRow);
×
89
    } else {
UNCOV
90
      updatedSelection.splice(selectedIndex, 1);
×
91
    }
UNCOV
92
    onRowSelected(updatedSelection);
×
93
  };
94

95
  const onSelectAllClick = () => {
70✔
UNCOV
96
    let newSelectedRows = Array.from({ length: items.length }, (_, index) => index);
×
UNCOV
97
    if (selectedRows.length && selectedRows.length <= items.length) {
×
UNCOV
98
      newSelectedRows = [];
×
99
    }
UNCOV
100
    onRowSelected(newSelectedRows);
×
101
  };
102

103
  return (
70✔
104
    <Table className={`margin-bottom ${className}`} style={style} ref={tableRef}>
105
      <TableHead className={classes.header}>
106
        <TableRow>
107
          {!!onRowSelected && (
108✔
108
            <TableCell>
109
              <Checkbox indeterminate={false} checked={selectedRows.length === items.length} onChange={onSelectAllClick} />
110
            </TableCell>
111
          )}
112
          {columns.map(column => (
113
            <HeaderItem key={column.key} columnKey={column.key} hasMultiSort={hasMultiSort} onSort={onChangeSorting} sortOptions={sort} {...column} />
328✔
114
          ))}
115
        </TableRow>
116
      </TableHead>
117
      <TableBody>
118
        {items.map((item, index) => (
119
          <TableRow className={onItemClick ? 'clickable' : ''} hover key={item.id || index}>
521✔
120
            {onRowSelected && (
939✔
121
              <TableCell>
UNCOV
122
                <Checkbox checked={selectedRows.includes(index)} onChange={() => onRowSelection(index)} />
×
123
              </TableCell>
124
            )}
125
            {columns.map(column => (
126
              <TableCell className="relative" key={column.key} onClick={() => (onItemClick ? onItemClick(item) : null)}>
2,076!
127
                {column.render(item, column.extras)}
128
              </TableCell>
129
            ))}
130
          </TableRow>
131
        ))}
132
      </TableBody>
133
    </Table>
134
  );
135
};
136

137
export default DetailsTable;
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