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

DLR-SC / ESID / 15442352070

04 Jun 2025 12:31PM UTC coverage: 51.036% (+0.3%) from 50.694%
15442352070

Pull #409

github

kunkoala
:bug: fixed variable name for card hiding after merging
Pull Request #409: Added cards drag and drop feature

399 of 512 branches covered (77.93%)

Branch coverage included in aggregate %.

141 of 157 new or added lines in 5 files covered. (89.81%)

1 existing line in 1 file now uncovered.

3837 of 7788 relevant lines covered (49.27%)

4.68 hits per line

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

98.51
/src/components/ScenarioComponents/CardsComponents/DataCard.tsx
1
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
2
// SPDX-License-Identifier: Apache-2.0
3

4
import Box from '@mui/material/Box';
1✔
5
import React, {Dispatch, useEffect, useMemo, useState} from 'react';
1✔
6
import MainCard from './MainCard/MainCard';
1✔
7
import FiltersContainer from './GroupFilter/FiltersContainer';
1✔
8
import {FilterValues} from 'types/card';
9
import {GroupFilter} from 'types/group';
10
import {Localization} from 'types/localization';
11
import {useSortable} from '@dnd-kit/sortable';
1✔
12
import {CSS} from '@dnd-kit/utilities';
1✔
13

14
interface DataCardProps {
15
  /** A unique identifier for the card.*/
16
  id: string;
17

18
  /** A dictionary of compartment values associated with the card.*/
19
  compartmentValues: Record<string, number | null> | null;
20

21
  /** A dictionary of start values used for calculating the rate. This determines whether the values have increased, decreased, or remained the same. */
22
  referenceValues: Record<string, number> | null;
23

24
  /** The title of the card.*/
25
  title: string;
26

27
  /** A boolean indicating whether the compartments are expanded.*/
28
  compartmentsExpanded: boolean;
29

30
  /** The compartment that is currently selected.*/
31
  selectedCompartmentId: string | null;
32

33
  /** A boolean indicating whether the scenario is selected.*/
34
  isSelected: boolean;
35

36
  /** The color of the card.*/
37
  color: string;
38

39
  /** if this scenario is active.*/
40
  isActive: boolean;
41

42
  /** A dictionary of filter values. This is an array of objects, each containing a title and a dictionary of numbers representing
43
   * the filtered information to be displayed, it's used a disctionary because each card has to have the same amount of filter. */
44
  filterValues?: Record<string, FilterValues[]> | null;
45

46
  /** A function to set the selected scenario.*/
47
  setSelected: Dispatch<{id: string; state: boolean}>;
48

49
  /** A function to set the active scenario.*/
50
  setActive: Dispatch<{id: string; state: boolean}>;
51

52
  /** A function to notify the parent that this scenario wants to be removed. */
53
  remove: Dispatch<string>;
54

55
  /** The minimum number of compartment rows.*/
56
  minCompartmentsRows: number;
57

58
  /** The maximum number of compartment rows.*/
59
  maxCompartmentsRows: number;
60

61
  /** An object containing localization information (translation & number formattation).*/
62
  localization?: Localization;
63

64
  /** A dictionary of group filters.*/
65
  groupFilters: Record<string, GroupFilter> | undefined;
66

67
  /** Boolean to determine if the card is draggable */
68
  draggable: boolean;
69

70
  /** Boolean to determine if the arrow is displayed */
71
  arrow?: boolean;
72
}
73

74
/**
75
 * This component renders a card for either the case data or the scenario cards. Each card contains a title, a list of
76
 * compartment values, and change rates relative to the simulation start. Additionally, the component includes a filter container.
77
 * The filter container renders a button and generates the necessary number of cards based on the presence of any filters.
78
 */
79
export default function DataCard({
22✔
80
  id,
22✔
81
  compartmentValues,
22✔
82
  referenceValues,
22✔
83
  title,
22✔
84
  compartmentsExpanded,
22✔
85
  selectedCompartmentId,
22✔
86
  filterValues,
22✔
87
  color,
22✔
88
  isActive,
22✔
89
  isSelected,
22✔
90
  minCompartmentsRows,
22✔
91
  maxCompartmentsRows,
22✔
92
  setSelected,
22✔
93
  setActive,
22✔
94
  remove,
22✔
95
  localization = {
22✔
96
    formatNumber: (value: number) => value.toString(),
22✔
97
    customLang: 'global',
22✔
98
    overrides: {},
22✔
99
  },
22✔
100
  groupFilters,
22✔
101
  draggable,
22✔
102
  arrow = true,
22✔
103
}: DataCardProps) {
22✔
104
  const [hover, setHover] = useState<boolean>(false);
22✔
105
  const [folded, setFolded] = useState<boolean>(false);
22✔
106
  const [visibility, setVisibility] = useState<boolean>(true);
22✔
107

108
  // drag and drop
109
  const {attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging, transition} = useSortable({
22✔
110
    id,
22✔
111
    disabled: {
22✔
112
      draggable: !draggable,
22✔
113
      droppable: !draggable,
22✔
114
    },
22✔
115
  });
22✔
116
  const style = {
22✔
117
    transform: CSS.Transform.toString(transform),
22✔
118
    transition,
22✔
119
  };
22✔
120

121
  const filteredTitles: string[] = useMemo(() => {
22✔
122
    if (isActive && filterValues?.[id.toString()]) {
13✔
123
      return filterValues[id.toString()].map((filterValue: FilterValues) => filterValue.filteredTitle);
4✔
124
    }
4✔
125
    return [];
9✔
126
  }, [isActive, filterValues, id]);
22✔
127

128
  const filteredValues = useMemo(() => {
22✔
129
    if (isActive && filterValues?.[id.toString()]) {
13✔
130
      return filterValues[id.toString()].map((filterValue: FilterValues) => filterValue.filteredValues);
4✔
131
    }
4✔
132
    return [];
9✔
133
  }, [isActive, filterValues, id]);
22✔
134

135
  /*
136
   * This useEffect hook updates the visibility of the component based on groupFilters and filteredTitles.
137
   * It checks if the first title in filteredTitles matches any filter name in groupFilters and if that filter is visible.
138
   * If at least one matching filter is visible, the component becomes visible; otherwise, it remains hidden.
139
   */
140
  useEffect(() => {
22✔
141
    function checkVisibility(): boolean {
13✔
142
      if (groupFilters) {
13✔
143
        return Object.values(groupFilters)
13✔
144
          .map((filter) => (filter.name == filteredTitles[0] ? filter.isVisible : false))
13✔
145
          .includes(true);
13✔
146
      }
13!
UNCOV
147
      return false;
×
148
    }
13✔
149
    setVisibility(checkVisibility);
13✔
150
  }, [filteredTitles, groupFilters]);
22✔
151

152
  return (
22✔
153
    <Box
22✔
154
      id={`data-card-${id}`}
22✔
155
      sx={{
22✔
156
        display: 'flex',
22✔
157
        flexDirection: 'row',
22✔
158
        alignItems: 'flex-start',
22✔
159
      }}
22✔
160
      ref={setNodeRef}
22✔
161
      style={style}
22✔
162
    >
163
      <MainCard
22✔
164
        id={id}
22✔
165
        label={title}
22✔
166
        hover={hover}
22✔
167
        color={color}
22✔
168
        referenceValues={referenceValues}
22✔
169
        compartmentValues={compartmentValues}
22✔
170
        setHover={setHover}
22✔
171
        compartmentsExpanded={compartmentsExpanded}
22✔
172
        selectedCompartmentId={selectedCompartmentId}
22✔
173
        isSelected={isSelected}
22✔
174
        isActive={isActive}
22✔
175
        setSelected={setSelected}
22✔
176
        setActive={setActive}
22✔
177
        hide={remove}
22✔
178
        minCompartmentsRows={minCompartmentsRows}
22✔
179
        maxCompartmentsRows={maxCompartmentsRows}
22✔
180
        localization={localization}
22✔
181
        arrow={arrow}
22✔
182
        dragListeners={listeners}
22✔
183
        dragAttributes={attributes}
22✔
184
        draggable={draggable}
22✔
185
        setActivatorNodeRef={setActivatorNodeRef}
22✔
186
        isDragging={isDragging}
22✔
187
      />
22✔
188
      {isActive && filterValues?.[id.toString()] && Object.keys(groupFilters || {}).length !== 0 && visibility && (
22✔
189
        <FiltersContainer
4✔
190
          id={id}
4✔
191
          color={color}
4✔
192
          filteredTitles={filteredTitles}
4✔
193
          folded={folded}
4✔
194
          setFolded={setFolded}
4✔
195
          compartmentsExpanded={compartmentsExpanded}
4✔
196
          selectedCompartmentId={selectedCompartmentId}
4✔
197
          filteredValues={filteredValues}
4✔
198
          minCompartmentsRows={minCompartmentsRows}
4✔
199
          maxCompartmentsRows={maxCompartmentsRows}
4✔
200
          localization={localization}
4✔
201
        />
4✔
202
      )}
203
    </Box>
22✔
204
  );
205
}
22✔
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

© 2026 Coveralls, Inc