diff --git a/src/web/components/sessionTimer/SessionTimer.jsx b/src/web/components/sessionTimer/SessionTimer.jsx
new file mode 100644
index 0000000000..6af1f28fb0
--- /dev/null
+++ b/src/web/components/sessionTimer/SessionTimer.jsx
@@ -0,0 +1,54 @@
+import {useEffect, useState} from 'react';
+
+import useUserSessionTimeout from 'web/utils/useUserSessionTimeout';
+import date from 'gmp/models/date';
+import {RefreshCcw} from 'lucide-react';
+import Divider from 'web/components/layout/divider';
+import {ActionIcon} from '@mantine/core';
+import useTranslation from 'web/hooks/useTranslation';
+
+const SessionTimer = () => {
+ const [sessionTimeout, renewSession] = useUserSessionTimeout();
+ const [timeLeft, setTimeLeft] = useState('');
+ const [_] = useTranslation();
+
+ useEffect(() => {
+ const updateTimeLeft = () => {
+ if (!sessionTimeout) {
+ return
Session timer is currently unavailable.
;
+ }
+ const now = date();
+ const duration = date.duration(sessionTimeout.diff(now));
+ if (duration.asSeconds() <= 0) {
+ setTimeLeft('00:00');
+ } else {
+ const formatted =
+ Math.floor(duration.asMinutes()) +
+ ':' +
+ ('0' + duration.seconds()).slice(-2);
+ setTimeLeft(formatted);
+ }
+ };
+
+ updateTimeLeft();
+ const intervalId = setInterval(updateTimeLeft, 1000);
+
+ return () => clearInterval(intervalId);
+ }, [sessionTimeout]);
+
+ return (
+
+ {timeLeft}
+
+
+
+
+ );
+};
+
+export default SessionTimer;
diff --git a/src/web/components/structure/header.jsx b/src/web/components/structure/header.jsx
index 8f8de43026..c56f272874 100644
--- a/src/web/components/structure/header.jsx
+++ b/src/web/components/structure/header.jsx
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
-import React, {useCallback} from 'react';
+import {useCallback} from 'react';
import {useHistory} from 'react-router-dom';
@@ -30,6 +30,7 @@ import useGmp from 'web/utils/useGmp';
import LogoutIcon from 'web/components/icon/logouticon';
import MySettingsIcon from 'web/components/icon/mysettingsicon';
import LanguageSwitch from './languageswitch';
+import SessionTimer from '../sessionTimer/SessionTimer';
const Header = () => {
const gmp = useGmp();
@@ -73,6 +74,7 @@ const Header = () => {
languageSwitch={}
menuPoints={menuPoints}
isLoggedIn={loggedIn}
+ sessionTimer={}
username={username}
logoLink="/"
/>
diff --git a/src/web/utils/__tests__/useUserSessionTimeout.jsx b/src/web/utils/__tests__/useUserSessionTimeout.jsx
index 9689be606f..34214a7fe9 100644
--- a/src/web/utils/__tests__/useUserSessionTimeout.jsx
+++ b/src/web/utils/__tests__/useUserSessionTimeout.jsx
@@ -22,16 +22,19 @@ import date from 'gmp/models/date';
import {setSessionTimeout as setSessionTimeoutAction} from 'web/store/usersettings/actions';
-import {rendererWith, fireEvent} from '../testing';
+import {rendererWith} from '../testing';
import useUserSessionTimeout from '../useUserSessionTimeout';
const TestUserSessionTimeout = () => {
const [sessionTimeout, setSessionTimeout] = useUserSessionTimeout();
return (
- setSessionTimeout(date('2020-03-10'))}>
+
+
);
};
@@ -47,20 +50,4 @@ describe('useUserSessionTimeout tests', () => {
expect(element).toHaveTextContent(/^10-10-19$/);
});
-
- test('should allow to set the users session timeout', () => {
- const {render, store} = rendererWith({store: true});
-
- const timeout = date('2019-10-10');
-
- store.dispatch(setSessionTimeoutAction(timeout));
-
- const {element} = render();
-
- expect(element).toHaveTextContent(/^10-10-19$/);
-
- fireEvent.click(element);
-
- expect(element).toHaveTextContent(/^10-03-20$/);
- });
});
diff --git a/src/web/utils/useUserSessionTimeout.jsx b/src/web/utils/useUserSessionTimeout.jsx
index 761600e4a1..317fe4c063 100644
--- a/src/web/utils/useUserSessionTimeout.jsx
+++ b/src/web/utils/useUserSessionTimeout.jsx
@@ -19,13 +19,29 @@ import {useSelector, useDispatch} from 'react-redux';
import {getSessionTimeout} from 'web/store/usersettings/selectors';
import {setSessionTimeout} from 'web/store/usersettings/actions';
+import useGmp from 'web/utils/useGmp';
+
+/**
+ * Custom hook to manage user session timeout.
+ *
+ * This hook provides the current session timeout, represented as a moment object, and a function to renew the session timeout through an API call.
+ * The `renewSessionAndUpdateTimeout` function makes an API call to renew the session and updates the session timeout based on the response, also represented as a moment object.
+ * This function does not require any parameters and will update the session timeout to the new value obtained from the API response.
+ *
+ * @returns {Array} An array containing the current `sessionTimeout` as a moment object and the `renewSessionAndUpdateTimeout` function.
+ */
const useUserSessionTimeout = () => {
+ const gmp = useGmp();
const dispatch = useDispatch();
- return [
- useSelector(getSessionTimeout),
- timeout => dispatch(setSessionTimeout(timeout)),
- ];
+ const sessionTimeout = useSelector(getSessionTimeout);
+
+ const renewSessionAndUpdateTimeout = async () => {
+ const response = await gmp.user.renewSession();
+ dispatch(setSessionTimeout(response.data));
+ };
+
+ return [sessionTimeout, renewSessionAndUpdateTimeout];
};
export default useUserSessionTimeout;