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

CBIIT / crdc-datahub-ui / 11940217181

20 Nov 2024 07:16PM UTC coverage: 55.305% (+1.5%) from 53.816%
11940217181

Pull #538

github

web-flow
Merge a5fbe1524 into 85b9e32a0
Pull Request #538: Misc Optimizations

2622 of 5208 branches covered (50.35%)

Branch coverage included in aggregate %.

3 of 20 new or added lines in 4 files covered. (15.0%)

12 existing lines in 2 files now uncovered.

3753 of 6319 relevant lines covered (59.39%)

141.8 hits per line

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

0.0
/src/components/InactivityDialog/InactivityDialog.tsx
1
import React, { useState, useEffect } from "react";
2
import { Button, Dialog, DialogTitle, styled } from "@mui/material";
3
import { useNavigate } from "react-router-dom";
4
import { useSnackbar } from "notistack";
5
import { useAuthContext } from "../Contexts/AuthContext";
6
import { Logger, secondsToMinuteString } from "../../utils";
7

8
const InactivityWarningDialog = styled(Dialog)({
×
9
  "& .MuiDialog-paper": {
10
    width: "550px",
11
    height: "320px",
12
    borderRadius: "8px",
13
    border: "2px solid var(--secondary-one, #0B7F99)",
14
    background: "linear-gradient(0deg, #F2F6FA 0%, #F2F6FA 100%), #2E4D7B",
15
    boxShadow: "0px 4px 45px 0px rgba(0, 0, 0, 0.40)",
16
  },
17
  "& #customized-dialog-title": {
18
    margin: 0,
19
    paddingLeft: "30px",
20
    backgroundColor: "#6D89A2",
21
    color: "#FFFFFF",
22
    fontFamily: "Lato",
23
    fontSize: "20px",
24
    fontWeight: 600,
25
    letterSpacing: 0,
26
  },
27
});
28

29
const InactivityWarningContent = styled("div")({
×
30
  margin: "50px auto",
31
  color: "#000000",
32
  fontFamily: "'Nunito', 'Rubik', sans-serif",
33
  fontSize: "17px",
34
  fontWeight: 300,
35
  letterSpacing: 0,
36
  lineHeight: "24px",
37
  "& .buttonWrapper": {
38
    display: "flex",
39
    justifyContent: "center",
40
    alignItems: "center",
41
    textAlign: "center",
42
  },
43
  "& .buttonGroup": {
44
    color: "#FFFFFF",
45
    fontFamily: "Lato",
46
    fontSize: "11px",
47
    lineHeight: "22px",
48
    width: "150px",
49
    border: "1px solid #626262",
50
    marginTop: "30px",
51
    borderRadius: "4px",
52
    fontWeight: 500,
53
  },
54
  "& .extendButton": {
55
    backgroundColor: "#566672 !important",
56
  },
57
  "& .logOutButton": {
58
    marginLeft: "20px",
59
    backgroundColor: "#437BBE !important",
60
  },
61
});
62

63
const SessionTimeoutDialog = styled(Dialog)({
×
64
  "& .MuiDialog-paper": {
65
    width: "550px",
66
    height: "320px",
67
    borderRadius: "8px",
68
    border: "2px solid var(--secondary-one, #0B7F99)",
69
    background: "linear-gradient(0deg, #F2F6FA 0%, #F2F6FA 100%), #2E4D7B",
70
    boxShadow: "0px 4px 45px 0px rgba(0, 0, 0, 0.40)",
71
  },
72
  "& .closeIcon": {
73
    cursor: "pointer",
74
    textAlign: "end",
75
  },
76
});
77

78
const SessionTimeoutContent = styled("div")({
×
79
  justifyContent: "space-between",
80
  paddingRight: "33px",
81
  paddingLeft: "33px",
82
  paddingTop: "10px",
83
  fontFamily: "lato",
84
  textAlign: "center",
85
  "& .sessionTimeoutTitle": {
86
    fontSize: "25px",
87
    fontWeight: "bold",
88
    paddingBottom: "12px",
89
    color: "#566672",
90
  },
91
  "& .sessionTimeoutMessage": {
92
    fontSize: "17px",
93
    paddingBottom: "14px",
94
  },
95
  "& .buttonWrapper": {
96
    display: "flex",
97
    justifyContent: "center",
98
    alignItems: "center",
99
    textAlign: "center",
100
  },
101
  "& .buttonGroup": {
102
    color: "#FFFFFF",
103
    fontFamily: "Lato",
104
    fontSize: "11px",
105
    lineHeight: "22px",
106
    width: "90px",
107
    border: "1px solid #626262",
108
    marginTop: "30px",
109
    borderRadius: "4px",
110
    fontWeight: 500,
111
  },
112
  "& .closeButton": {
113
    backgroundColor: "#566672 !important",
114
  },
115
  "& .loginButton": {
116
    marginLeft: "20px",
117
    backgroundColor: "#437BBE !important",
118
  },
119
});
120

NEW
121
const thresholdTime = 300;
×
122

123
const InactivityDialog = () => {
×
124
  const navigate = useNavigate();
×
NEW
125
  const { enqueueSnackbar } = useSnackbar();
×
NEW
126
  const { isLoggedIn, logout } = useAuthContext();
×
127

NEW
128
  const [warning, setWarning] = useState<boolean>(false);
×
NEW
129
  const [timedOut, setTimedOut] = useState<boolean>(false);
×
NEW
130
  const [timeLeft, setTimeLeft] = useState<number>(thresholdTime);
×
131

132
  const extendSession = async () => {
×
133
    try {
×
NEW
134
      const res = await fetch(`${window.origin}/api/authn/authenticated`, {
×
135
        method: "POST",
136
        headers: {
137
          Accept: "application/json",
138
          "Content-Type": "application/json",
139
        },
140
      })
141
        .then((response) => response.json())
×
142
        .catch(() => {});
143

144
      if (res.status) {
×
145
        setWarning(false);
×
146
      }
147
    } catch (e) {
NEW
148
      Logger.error("Error in extending session", e);
×
149
    }
150
  };
151

152
  const handleExtendSession = () => {
×
153
    extendSession();
×
154
  };
155

156
  const handleSignOutNoBanner = async () => {
×
NEW
157
    const logoutStatus = await logout();
×
158
    if (logoutStatus) {
×
159
      navigate("/");
×
160
      setWarning(false);
×
161
    }
162
  };
163

164
  const handleSignOut = async () => {
×
NEW
165
    const logoutStatus = await logout();
×
166
    if (logoutStatus) {
×
167
      navigate("/");
×
168
      setWarning(false);
×
NEW
169
      enqueueSnackbar("You have been logged out.", { variant: "default" });
×
170
    }
171
  };
172

173
  const loadData = async () => {
×
174
    try {
×
NEW
175
      const res = await fetch(`${window.origin}/api/authn/session-ttl`);
×
UNCOV
176
      const data = await res.json();
×
177
      const { ttl } = data;
×
178
      if (ttl <= 0) {
×
179
        // If user did not select any option and timed out in BE.
180
        handleSignOutNoBanner();
×
181
        setTimedOut(true);
×
182
      } else if (ttl > 0 && ttl <= thresholdTime) {
×
183
        setTimeLeft(ttl);
×
184
        setWarning(true);
×
185
      }
186
    } catch (e) {
NEW
187
      Logger.error("Error in fetching session ttl", e);
×
188
    }
189
  };
190

191
  useEffect(() => {
×
192
    let ID: NodeJS.Timer;
UNCOV
193
    if (isLoggedIn) {
×
NEW
194
      ID = setInterval(loadData, 10 * 1000);
×
195
    } else {
NEW
196
      clearInterval(ID);
×
197
    }
198

NEW
199
    return () => clearInterval(ID);
×
200
  }, [isLoggedIn]);
201

202
  return (
×
203
    <>
204
      <InactivityWarningDialog open={warning}>
205
        <DialogTitle id="customized-dialog-title">Session Timeout Warning</DialogTitle>
206
        <InactivityWarningContent>
207
          This session is about to expire due to inactivity.
208
          <br />
209
          You will be logged out in
210
          {` ${secondsToMinuteString(timeLeft)} `}
211
          minutes.
212
          <br />
213
          Please elect to extend this session or logout.
214
          <div className="buttonWrapper">
215
            <Button
216
              variant="contained"
217
              className="buttonGroup extendButton"
218
              onClick={handleExtendSession}
219
              disableElevation={false}
220
            >
221
              EXTEND SESSION
222
            </Button>
223
            <Button
224
              variant="contained"
225
              className="buttonGroup logOutButton"
226
              onClick={handleSignOut}
227
              disableElevation={false}
228
            >
229
              LOGOUT
230
            </Button>
231
          </div>
232
        </InactivityWarningContent>
233
      </InactivityWarningDialog>
234
      <SessionTimeoutDialog open={timedOut}>
235
        <DialogTitle>
236
          <div
237
            role="button"
238
            className="closeIcon"
239
            onClick={() => setTimedOut(false)}
×
240
            tabIndex={0}
241
            onKeyDown={(e) => {
242
              if (e.key === "Enter") {
×
243
                setTimedOut(false);
×
244
              }
245
            }}
246
          >
247
            <img
248
              style={{ height: 10, marginBottom: 2 }}
249
              src="https://raw.githubusercontent.com/CBIIT/datacommons-assets/main/bento/images/icons/svgs/LocalFindCaseDeleteIcon.svg"
250
              alt="close icon"
251
            />
252
          </div>
253
        </DialogTitle>
254
        <SessionTimeoutContent>
255
          <div className="sessionTimeoutTitle">Your session has expired.</div>
256
          <br />
257
          <div className="sessionTimeoutMessage">Please login again to continue working.</div>
258
          <div className="buttonWrapper">
259
            <Button
260
              variant="contained"
261
              className="buttonGroup closeButton"
262
              onClick={() => setTimedOut(false)}
×
263
              disableElevation={false}
264
            >
265
              CLOSE
266
            </Button>
267
            <Button
268
              variant="contained"
269
              className="buttonGroup loginButton"
270
              onClick={() => {
271
                setTimedOut(false);
×
272
                navigate("login");
×
273
              }}
274
              disableElevation={false}
275
            >
276
              LOGIN
277
            </Button>
278
          </div>
279
        </SessionTimeoutContent>
280
      </SessionTimeoutDialog>
281
    </>
282
  );
283
};
284

285
export default InactivityDialog;
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