Skip to content

Commit

Permalink
Add: Session timer
Browse files Browse the repository at this point in the history
  • Loading branch information
daniele-mng authored and timopollmeier committed Jul 19, 2024
1 parent 9b46f3b commit 7810a80
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 24 deletions.
54 changes: 54 additions & 0 deletions src/web/components/sessionTimer/SessionTimer.jsx
Original file line number Diff line number Diff line change
@@ -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 <div>Session timer is currently unavailable.</div>;
}
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 (
<Divider>
<span>{timeLeft}</span>
<ActionIcon
onClick={renewSession}
variant="transparent"
color="neutral.0"
title={_('Renew session timeout')}
>
<RefreshCcw size={16} />
</ActionIcon>
</Divider>
);
};

export default SessionTimer;
4 changes: 3 additions & 1 deletion src/web/components/structure/header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, {useCallback} from 'react';
import {useCallback} from 'react';

import {useHistory} from 'react-router-dom';

Expand All @@ -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();
Expand Down Expand Up @@ -73,6 +74,7 @@ const Header = () => {
languageSwitch={<LanguageSwitch />}
menuPoints={menuPoints}
isLoggedIn={loggedIn}
sessionTimer={<SessionTimer />}
username={username}
logoLink="/"
/>
Expand Down
25 changes: 6 additions & 19 deletions src/web/utils/__tests__/useUserSessionTimeout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<span onClick={() => setSessionTimeout(date('2020-03-10'))}>
<button
onClick={() => setSessionTimeout(date('2020-03-10'))}
onKeyDown={() => {}}
>
{dateFormat(sessionTimeout, 'DD-MM-YY')}
</span>
</button>
);
};

Expand All @@ -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(<TestUserSessionTimeout />);

expect(element).toHaveTextContent(/^10-10-19$/);

fireEvent.click(element);

expect(element).toHaveTextContent(/^10-03-20$/);
});
});
24 changes: 20 additions & 4 deletions src/web/utils/useUserSessionTimeout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

0 comments on commit 7810a80

Please sign in to comment.