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

CBIIT / crdc-datahub-ui / 18789341118

24 Oct 2025 06:57PM UTC coverage: 78.178% (+15.5%) from 62.703%
18789341118

push

github

web-flow
Merge pull request #888 from CBIIT/3.4.0

3.4.0 Release

4977 of 5488 branches covered (90.69%)

Branch coverage included in aggregate %.

8210 of 9264 new or added lines in 257 files covered. (88.62%)

6307 existing lines in 120 files now uncovered.

30203 of 39512 relevant lines covered (76.44%)

213.36 hits per line

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

57.83
/src/components/Header/components/NavbarDesktopDropdown.tsx
1
import { Button, styled } from "@mui/material";
1✔
2
import Grid from "@mui/material/Unstable_Grid2";
1✔
3
import { Link } from "react-router-dom";
1✔
4

5
import { hasPermission, Permissions } from "../../../config/AuthPermissions";
1✔
6
import { ActionId, HeaderLinks } from "../../../config/HeaderConfig";
1✔
7
import { Status, useAuthContext } from "../../Contexts/AuthContext";
1✔
8
import SuspenseLoader from "../../SuspenseLoader";
1✔
9

10
const Dropdown = styled("div")({
1✔
11
  left: 0,
1✔
12
  right: 0,
1✔
13
  width: "100%",
1✔
14
  background: "#1F4671",
1✔
15
  zIndex: 1100,
1✔
16
  display: "block",
1✔
17
  position: "absolute",
1✔
18
  paddingTop: "35px",
1✔
19
  paddingBottom: "12px",
1✔
20
  "&.invisible": {
1✔
21
    visibility: "hidden",
1✔
22
  },
1✔
23
});
1✔
24

25
const StyledGridContainer = styled(Grid)({
1✔
26
  margin: "0 auto",
1✔
27
  textAlign: "left",
1✔
28
  position: "relative",
1✔
29
  maxWidth: "1400px",
1✔
30
  padding: "0 16px",
1✔
31
  "& .dropdownList": {
1✔
32
    padding: 0,
1✔
33
    marginTop: 0,
1✔
34
    marginBottom: "45px",
1✔
35
    listStyle: "none",
1✔
36
  },
1✔
37
  "& .gridItem": {
1✔
38
    paddingLeft: "12px",
1✔
39
    paddingRight: "12px",
1✔
40
  },
1✔
41
  "& .dropdownListItem": {
1✔
42
    padding: 0,
1✔
43
    margin: 0,
1✔
44
    lineHeight: "22px",
1✔
45
    height: "22px",
1✔
46
  },
1✔
47
  "& .dropdownItem": {
1✔
48
    padding: "0",
1✔
49
    textAlign: "left",
1✔
50
    fontFamily: "'Poppins', sans-serif",
1✔
51
    fontStyle: "normal",
1✔
52
    fontWeight: 600,
1✔
53
    fontSize: "20px",
1✔
54
    lineHeight: "22px",
1✔
55
    color: "#FFFFFF",
1✔
56
    textDecoration: "none",
1✔
57
    cursor: "pointer",
1✔
58
    whiteSpace: "pre-line",
1✔
59
    "&:hover": {
1✔
60
      textDecoration: "underline",
1✔
61
    },
1✔
62
  },
1✔
63
  "& a.dropdownItem": {
1✔
64
    display: "inline-block",
1✔
65
    padding: "0",
1✔
66
  },
1✔
67
  "& .dropdownItemButton": {
1✔
68
    textTransform: "none",
1✔
69
    paddingLeft: 0,
1✔
70
    "&:hover": {
1✔
71
      background: "transparent",
1✔
72
    },
1✔
73
  },
1✔
74
  "#navbar-dropdown-item-name-logout": {
1✔
75
    maxWidth: "200px",
1✔
76
  },
1✔
77
});
1✔
78

79
type Props = {
80
  clickedTitle: string;
81
  onTitleClick?: (title: string) => void;
82
  onItemClick?: (item: ActionId) => void;
83
};
84

85
const NavbarDesktopDropdown = ({ clickedTitle, onTitleClick, onItemClick }: Props) => {
1✔
86
  const { user, status: AuthStatus } = useAuthContext();
3✔
87

88
  const checkPermissions = (permissions: AuthPermissions[]) => {
3✔
89
    if (!permissions?.length) {
×
90
      return true; // No permissions required
×
UNCOV
91
    }
×
92

93
    return permissions.every((permission) => {
×
94
      const [entityRaw, actionRaw] = permission.split(":", 2);
×
95

96
      if (!entityRaw || !actionRaw) {
×
97
        return false;
×
UNCOV
98
      }
×
99

100
      const entity = entityRaw as keyof Permissions;
×
101
      const action = actionRaw as Permissions[keyof Permissions]["action"];
×
102

103
      return hasPermission(user, entity, action, null, true);
×
UNCOV
104
    });
×
UNCOV
105
  };
×
106

107
  if (AuthStatus === Status.LOADING) {
3!
108
    return <SuspenseLoader />;
×
UNCOV
109
  }
×
110

111
  const dropdownLinks: NavBarItem | undefined = HeaderLinks.find(
3✔
112
    (link) => link.name === clickedTitle
3✔
113
  );
3✔
114

115
  // Get completely empty columns due to insufficient permissions
116
  const emptyColumns =
3✔
117
    dropdownLinks?.columns?.filter(
3!
118
      (c) => c.some((r) => r.permissions) && c.every((r) => !checkPermissions(r.permissions || []))
3✔
119
    ) || [];
3✔
120

121
  return (
3✔
122
    <Dropdown className={clickedTitle === "" ? "invisible" : ""}>
3!
123
      <StyledGridContainer container>
3✔
124
        {clickedTitle !== ""
3!
UNCOV
125
          ? dropdownLinks?.columns?.map((column, columnIdx) => {
×
126
              if (!column?.length || emptyColumns.includes(column)) {
×
127
                return null;
×
UNCOV
128
              }
×
129

130
              return (
×
131
                // eslint-disable-next-line react/no-array-index-key
UNCOV
132
                <Grid xs={3} key={`column-${columnIdx}`}>
×
UNCOV
133
                  {column.map((dropItem, rowIdx) => {
×
134
                    const hasEveryPermission = checkPermissions(dropItem?.permissions);
×
135
                    if (!hasEveryPermission) {
×
136
                      // eslint-disable-next-line react/no-array-index-key
137
                      return <Grid xs={3} key={`empty-${columnIdx}-${rowIdx}`} />;
×
UNCOV
138
                    }
×
139

140
                    if (dropItem.link) {
×
141
                      return (
×
UNCOV
142
                        <Grid xs={3} key={dropItem.id} className="gridItem">
×
UNCOV
143
                          <ul className="dropdownList">
×
UNCOV
144
                            <li className="dropdownListItem">
×
UNCOV
145
                              <Link
×
UNCOV
146
                                target={
×
UNCOV
147
                                  dropItem.link.startsWith("https://") ||
×
UNCOV
148
                                  dropItem.link.endsWith(".pdf")
×
UNCOV
149
                                    ? "_blank"
×
UNCOV
150
                                    : "_self"
×
151
                                }
UNCOV
152
                                id={dropItem.id}
×
UNCOV
153
                                to={dropItem.link}
×
UNCOV
154
                                className="dropdownItem"
×
155
                                onClick={() => onTitleClick("")}
×
156
                              >
UNCOV
157
                                {dropItem.name}
×
UNCOV
158
                                {dropItem.text && (
×
UNCOV
159
                                  <div className="dropdownItemText">{dropItem.text}</div>
×
160
                                )}
UNCOV
161
                              </Link>
×
UNCOV
162
                            </li>
×
UNCOV
163
                          </ul>
×
UNCOV
164
                        </Grid>
×
165
                      );
UNCOV
166
                    }
×
167

168
                    return (
×
UNCOV
169
                      <Grid xs={3} key={dropItem.id} className="gridItem">
×
UNCOV
170
                        <ul className="dropdownList">
×
UNCOV
171
                          <li className="dropdownListItem">
×
UNCOV
172
                            <Button
×
UNCOV
173
                              id={dropItem.id}
×
UNCOV
174
                              key={dropItem.id}
×
UNCOV
175
                              className="dropdownItem dropdownItemButton"
×
176
                              onClick={() => onItemClick?.(dropItem.actionId as ActionId)}
×
177
                            >
UNCOV
178
                              {dropItem.name}
×
UNCOV
179
                            </Button>
×
UNCOV
180
                          </li>
×
UNCOV
181
                        </ul>
×
UNCOV
182
                      </Grid>
×
183
                    );
UNCOV
184
                  })}
×
UNCOV
185
                </Grid>
×
186
              );
UNCOV
187
            })
×
188
          : null}
3✔
189
      </StyledGridContainer>
3✔
190
    </Dropdown>
3✔
191
  );
192
};
3✔
193

194
export default NavbarDesktopDropdown;
1✔
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