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

CBIIT / crdc-datahub-ui / 11144627467

02 Oct 2024 01:23PM UTC coverage: 48.539% (+0.2%) from 48.343%
11144627467

push

github

GitHub
Merge pull request #468 from CBIIT/CRDCDH-1500

2058 of 4764 branches covered (43.2%)

Branch coverage included in aggregate %.

2976 of 5607 relevant lines covered (53.08%)

128.02 hits per line

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

40.72
/src/components/Header/components/HeaderTabletAndMobile.tsx
1
import React, { HTMLProps, useEffect, useState } from "react";
2
import { NavLink, Link, useNavigate, useLocation } from "react-router-dom";
3
import { styled } from "@mui/material";
4
import Logo from "./LogoMobile";
5
import menuClearIcon from "../../../assets/header/Menu_Cancel_Icon.svg";
6
import rightArrowIcon from "../../../assets/header/Right_Arrow.svg";
7
import leftArrowIcon from "../../../assets/header/Left_Arrow.svg";
8
import { navMobileList, navbarSublists } from "../../../config/HeaderConfig";
9
import { GenerateApiTokenRoles } from "../../../config/AuthRoles";
10
import { useAuthContext } from "../../Contexts/AuthContext";
11
import GenericAlert from "../../GenericAlert";
12
import APITokenDialog from "../../APITokenDialog";
13
import UploaderToolDialog from "../../UploaderToolDialog";
14

15
const HeaderBanner = styled("div")({
2✔
16
  width: "100%",
17
});
18

19
const HeaderContainer = styled("div")({
2✔
20
  margin: "0 auto",
21
  paddingLeft: "16px",
22
  boxShadow: "-0.1px 6px 9px -6px rgba(0, 0, 0, 0.5)",
23
  "& .headerLowerContainer": {
24
    display: "flex",
25
    margin: "16px 0 4px 0",
26
    height: "51px",
27
  },
28
  "& .menuButton": {
29
    width: "89px",
30
    height: "45px",
31
    background: "#1F4671",
32
    borderRadius: "5px",
33
    fontFamily: "Open Sans",
34
    fontWeight: 700,
35
    fontSize: "20px",
36
    lineHeight: "45px",
37
    color: "#FFFFFF",
38
    textAlign: "center",
39
    "&:hover": {
40
      cursor: "pointer",
41
    },
42
  },
43
});
44

45
const NavMobileContainer = styled("div", {
2✔
46
  shouldForwardProp: (prop) => prop !== "display",
6✔
47
})<HTMLProps<HTMLDivElement> & { display: string }>(({ display }) => ({
2✔
48
  display,
49
  position: "absolute",
50
  left: 0,
51
  top: 0,
52
  height: "100%",
53
  width: "100%",
54
  zIndex: 1200,
55
}));
56

57
const MenuArea = styled("div")({
2✔
58
  height: "100%",
59
  width: "100%",
60
  display: "flex",
61
  "& .menuContainer": {
62
    background: "#ffffff",
63
    width: "300px",
64
    height: "100%",
65
    padding: "21px 16px",
66
  },
67
  "& .greyContainer": {
68
    width: "100%",
69
    height: "100%",
70
    background: "rgba(0,0,0,.2)",
71
  },
72
  "& .closeIcon": {
73
    height: "14px",
74
    marginBottom: "29px",
75
  },
76
  "& .closeIconImg": {
77
    float: "right",
78
    "&:hover": {
79
      cursor: "pointer",
80
    },
81
  },
82
  "& .backButton": {
83
    fontFamily: "Open Sans",
84
    fontWeight: 600,
85
    fontSize: "16px",
86
    lineHeight: "16px",
87
    color: "#007BBD",
88
    paddingLeft: "16px",
89
    background: `url(${leftArrowIcon}) left no-repeat`,
90
    "&:hover": {
91
      cursor: "pointer",
92
    },
93
  },
94
  "& .navMobileContainer": {
95
    padding: "24px 0 0 0",
96
    "& a": {
97
      textDecoration: "none",
98
      color: "#3D4551",
99
    },
100
  },
101
  "& .navMobileItem": {
102
    width: "268px",
103
    padding: "8px 24px 8px 16px",
104
    fontFamily: "Open Sans",
105
    fontWeight: 400,
106
    fontSize: "16px",
107
    lineHeight: "16px",
108
    borderTop: "1px solid #F0F0F0",
109
    borderBottom: "1px solid #F0F0F0",
110
    color: "#3D4551",
111
    "&:hover": {
112
      backgroundColor: "#f9f9f7",
113
    },
114
  },
115
  "& .SubItem": {
116
    paddingLeft: "24px",
117
  },
118
  "& .clickable": {
119
    background: `url(${rightArrowIcon}) 90% no-repeat`,
120
    cursor: "pointer",
121
  },
122
  "& .action": {
123
    cursor: "pointer",
124
  },
125
});
126

127
const Header = () => {
2✔
128
  const { isLoggedIn, user, logout } = useAuthContext();
2✔
129
  const navigate = useNavigate();
2✔
130
  const location = useLocation();
2✔
131

132
  const [navMobileDisplay, setNavMobileDisplay] = useState("none");
2✔
133
  const [openAPITokenDialog, setOpenAPITokenDialog] = useState<boolean>(false);
2✔
134
  const [uploaderToolOpen, setUploaderToolOpen] = useState<boolean>(false);
2✔
135
  const [selectedList, setSelectedList] = useState<NavBarItem[] | NavBarSubItem[]>(navMobileList);
2✔
136
  const [showLogoutAlert, setShowLogoutAlert] = useState<boolean>(false);
2✔
137
  const [restorePath, setRestorePath] = useState<string | null>(null);
2✔
138

139
  const displayName = user?.firstName || "N/A";
2✔
140

141
  const handleLogout = async () => {
2✔
142
    const logoutStatus = await logout?.();
×
143
    if (logoutStatus) {
×
144
      navigate("/");
×
145
      setShowLogoutAlert(true);
×
146
      setTimeout(() => setShowLogoutAlert(false), 10000);
×
147
    }
148
  };
149

150
  navbarSublists[displayName] = [
2✔
151
    {
152
      name: "User Profile",
153
      link: `/profile/${user?._id}`,
154
      id: "navbar-dropdown-item-user-profile",
155
      className: "navMobileSubItem",
156
    },
157
    {
158
      name: "Uploader CLI Tool",
159
      onClick: () => setUploaderToolOpen(true),
×
160
      id: "navbar-dropdown-item-uploader-tool",
161
      className: "navMobileSubItem action",
162
    },
163
    {
164
      name: "Logout",
165
      link: "/logout",
166
      id: "navbar-dropdown-item-logout",
167
      className: "navMobileSubItem",
168
    },
169
  ];
170

171
  if (user?.role === "Admin" || user?.role === "Organization Owner") {
2!
172
    navbarSublists[displayName].splice(1, 0, {
×
173
      name: "Manage Users",
174
      link: "/users",
175
      id: "navbar-dropdown-item-user-manage",
176
      className: "navMobileSubItem",
177
    });
178
  }
179
  if (user?.role === "Admin") {
2✔
180
    navbarSublists[displayName].splice(1, 0, {
×
181
      name: "Manage Organizations",
182
      link: "/organizations",
183
      id: "navbar-dropdown-item-organization-manage",
184
      className: "navMobileSubItem",
185
    });
186
  }
187
  if (user?.role === "Admin") {
2✔
188
    navbarSublists[displayName].splice(1, 0, {
×
189
      name: "Manage Studies",
190
      link: "/studies",
191
      id: "navbar-dropdown-item-studies-manage",
192
      className: "navMobileSubItem",
193
    });
194
  }
195
  if (user?.role && GenerateApiTokenRoles.includes(user?.role)) {
2!
196
    navbarSublists[displayName].splice(1, 0, {
×
197
      name: "API Token",
198
      onClick: () => setOpenAPITokenDialog(true),
×
199
      id: "navbar-dropdown-item-api-token",
200
      className: "navMobileSubItem action",
201
    });
202
  }
203

204
  const clickNavItem = (e) => {
2✔
205
    const clickTitle = e.target.innerText;
×
206
    setSelectedList(navbarSublists[clickTitle]);
×
207
  };
208

209
  useEffect(() => {
2✔
210
    if (!location?.pathname || location?.pathname === "/") {
2!
211
      setRestorePath(null);
2✔
212
      return;
2✔
213
    }
214

215
    setRestorePath(location?.pathname);
×
216
  }, [location]);
217

218
  return (
2✔
219
    <>
220
      <GenericAlert open={showLogoutAlert}>
221
        <span>You have been logged out.</span>
222
      </GenericAlert>
223
      <HeaderBanner data-testid="navigation-header-mobile">
224
        <HeaderContainer>
225
          <Logo />
226
          <div className="headerLowerContainer">
227
            <div
228
              role="button"
229
              id="header-navbar-open-menu-button"
230
              tabIndex={0}
231
              className="menuButton"
232
              onKeyDown={(e) => {
233
                if (e.key === "Enter") {
×
234
                  setNavMobileDisplay("block");
×
235
                }
236
              }}
237
              onClick={() => setNavMobileDisplay("block")}
×
238
            >
239
              Menu
240
            </div>
241
          </div>
242
        </HeaderContainer>
243
      </HeaderBanner>
244
      <NavMobileContainer display={navMobileDisplay}>
245
        <MenuArea>
246
          <div className="menuContainer">
247
            <div
248
              role="button"
249
              id="navbar-close-navbar-button"
250
              tabIndex={0}
251
              className="closeIcon"
252
              onKeyDown={(e) => {
253
                if (e.key === "Enter") {
×
254
                  setNavMobileDisplay("none");
×
255
                }
256
              }}
257
              onClick={() => setNavMobileDisplay("none")}
×
258
            >
259
              <img className="closeIconImg" src={menuClearIcon} alt="menuClearButton" />
260
            </div>
261
            {selectedList !== navMobileList && (
1!
262
              <div
263
                role="button"
264
                id="navbar-back-to-main-menu-button"
265
                tabIndex={0}
266
                className="backButton"
267
                onKeyDown={(e) => {
268
                  if (e.key === "Enter") {
×
269
                    setSelectedList(navMobileList);
×
270
                  }
271
                }}
272
                onClick={() => setSelectedList(navMobileList)}
×
273
              >
274
                Main Menu
275
              </div>
276
            )}
277
            <div className="navMobileContainer">
278
              {selectedList.map((navMobileItem) => {
279
                // If the user is not logged in and the item requires a role, don't show it
280
                if (
12✔
281
                  "roles" in navMobileItem &&
8✔
282
                  Array.isArray(navMobileItem?.roles) &&
283
                  !navMobileItem.roles.includes(user?.role)
284
                ) {
285
                  return null;
2✔
286
                }
287

288
                return (
10✔
289
                  <React.Fragment key={`mobile_${navMobileItem.id}`}>
290
                    {navMobileItem.className === "navMobileItem" && (
8✔
291
                      <NavLink
292
                        id={navMobileItem.id}
293
                        to={navMobileItem.link}
294
                        target={navMobileItem.link.startsWith("https://") ? "_blank" : "_self"}
3✔
295
                        onClick={() => setNavMobileDisplay("none")}
×
296
                      >
297
                        <div className="navMobileItem">{navMobileItem.name}</div>
298
                      </NavLink>
299
                    )}
300
                    {navMobileItem.className === "navMobileItem clickable" && (
7✔
301
                      <div
302
                        id={navMobileItem.id}
303
                        role="button"
304
                        tabIndex={0}
305
                        className="navMobileItem clickable"
306
                        onKeyDown={(e) => {
307
                          if (e.key === "Enter") {
×
308
                            clickNavItem(e);
×
309
                          }
310
                        }}
311
                        onClick={clickNavItem}
312
                      >
313
                        {navMobileItem.name}
314
                      </div>
315
                    )}
316
                    {navMobileItem.className === "navMobileSubItem action" &&
10!
317
                    "onClick" in navMobileItem &&
318
                    typeof navMobileItem.onClick === "function" ? (
319
                      <div
320
                        id={navMobileItem.id}
321
                        role="button"
322
                        tabIndex={0}
323
                        className="navMobileItem SubItem action"
324
                        onKeyDown={(e) => {
325
                          if (e.key === "Enter") {
×
326
                            navMobileItem.onClick();
×
327
                          }
328
                        }}
329
                        onClick={() => navMobileItem.onClick()}
×
330
                      >
331
                        {navMobileItem.name}
332
                      </div>
333
                    ) : null}
334
                    {navMobileItem.className === "navMobileSubItem" && (
5!
335
                      <Link
336
                        id={navMobileItem.id}
337
                        to={navMobileItem.link}
338
                        target={
339
                          navMobileItem.link.startsWith("https://") ||
×
340
                          navMobileItem.link.endsWith(".pdf")
341
                            ? "_blank"
342
                            : "_self"
343
                        }
344
                      >
345
                        <div
346
                          role="button"
347
                          tabIndex={0}
348
                          className="navMobileItem SubItem"
349
                          onKeyDown={(e) => {
350
                            if (e.key === "Enter") {
×
351
                              setNavMobileDisplay("none");
×
352
                              if (navMobileItem.name === "Logout") {
×
353
                                handleLogout();
×
354
                                setSelectedList(navMobileList);
×
355
                              }
356
                            }
357
                          }}
358
                          onClick={() => {
359
                            setNavMobileDisplay("none");
×
360
                            if (navMobileItem.name === "Logout") {
×
361
                              handleLogout();
×
362
                              setSelectedList(navMobileList);
×
363
                            }
364
                          }}
365
                        >
366
                          {navMobileItem.name}
367
                        </div>
368
                      </Link>
369
                    )}
370
                    {navMobileItem.className === "navMobileSubTitle" && (
5!
371
                      <div className="navMobileItem">{navMobileItem.name}</div>
372
                    )}
373
                  </React.Fragment>
374
                );
375
              })}
376
              {/* eslint-disable-next-line no-nested-ternary */}
377
              {selectedList === navMobileList ? (
1!
378
                isLoggedIn ? (
1!
379
                  <div
380
                    id="navbar-dropdown-name"
381
                    role="button"
382
                    tabIndex={0}
383
                    className="navMobileItem clickable"
384
                    onKeyDown={(e) => {
385
                      if (e.key === "Enter") {
×
386
                        clickNavItem(e);
×
387
                      }
388
                    }}
389
                    onClick={clickNavItem}
390
                  >
391
                    {displayName}
392
                  </div>
393
                ) : (
394
                  <Link
395
                    id="navbar-link-login"
396
                    to="/login"
397
                    state={{ redirectURLOnLoginSuccess: restorePath }}
398
                  >
399
                    <div
400
                      role="button"
401
                      tabIndex={0}
402
                      className="navMobileItem"
403
                      onKeyDown={(e) => {
404
                        if (e.key === "Enter") {
×
405
                          setNavMobileDisplay("none");
×
406
                        }
407
                      }}
408
                      onClick={() => setNavMobileDisplay("none")}
×
409
                    >
410
                      Login
411
                    </div>
412
                  </Link>
413
                )
414
              ) : null}
415
            </div>
416
          </div>
417
          <div
418
            role="button"
419
            id="navbar-close-navbar-grey-section"
420
            tabIndex={0}
421
            className="greyContainer"
422
            onKeyDown={(e) => {
423
              if (e.key === "Enter") {
×
424
                setNavMobileDisplay("none");
×
425
              }
426
            }}
427
            onClick={() => setNavMobileDisplay("none")}
×
428
            aria-label="greyContainer"
429
          />
430
        </MenuArea>
431
        <APITokenDialog open={openAPITokenDialog} onClose={() => setOpenAPITokenDialog(false)} />
×
432
        <UploaderToolDialog open={uploaderToolOpen} onClose={() => setUploaderToolOpen(false)} />
×
433
      </NavMobileContainer>
434
    </>
435
  );
436
};
437

438
export default Header;
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