Skip to content

Commit

Permalink
add: user settings time and date format
Browse files Browse the repository at this point in the history
  • Loading branch information
daniele-mng committed Oct 16, 2024
1 parent d5c6502 commit 532c646
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 84 deletions.
8 changes: 8 additions & 0 deletions src/gmp/commands/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ export const DEFAULT_FILTER_SETTINGS = {
vulnerability: '17c9d269-95e7-4bfa-b1b2-bc106a2175c7',
};

const PARAM_KEYS = {
DATE: 'date_format',
TIME: 'time_format',
};

const saveDefaultFilterSettingId = entityType =>
`settings_filter:${DEFAULT_FILTER_SETTINGS[entityType]}`;

Expand Down Expand Up @@ -251,9 +256,12 @@ export class UserCommand extends EntityCommand {

saveSettings(data) {
log.debug('Saving settings', data);

return this.httpPost({
cmd: 'save_my_settings',
text: data.timezone,
[PARAM_KEYS.DATE]: data.dateFormat,
[PARAM_KEYS.TIME]: data.timeFormat,
old_password: data.oldPassword,
password: data.newPassword,
lang: data.userInterfaceLanguage,
Expand Down
47 changes: 41 additions & 6 deletions src/gmp/locale/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const ensureDate = date => {
return date;
};

export const dateFormat = (date, format, tz) => {
export const getFormattedDate = (date, format, tz) => {
date = ensureDate(date);
if (!isDefined(date)) {
return undefined;
Expand All @@ -43,14 +43,49 @@ export const dateFormat = (date, format, tz) => {
if (isDefined(tz)) {
date.tz(tz);
}

return date.format(format);
};

export const shortDate = (date, tz) => dateFormat(date, 'L', tz);
export const dateTimeFormatOptions = {
time: {12: 'h:mm A', 24: 'H:mm'},
date: {wmdy: 'ddd, MMM D, YYYY', wdmy: 'ddd, D MMM YYYY'},
};

export const shortDate = (date, tz, userInterfaceDateFormat) => {
const formatString = dateTimeFormatOptions.date[userInterfaceDateFormat]
? 'DD/MM/YYYY'
: 'L';

return getFormattedDate(date, formatString, tz);
};

export const longDate = (
date,
tz,
userInterfaceTimeFormat,
userInterfaceDateFormat,
) => {
const formatString =
dateTimeFormatOptions.date[userInterfaceDateFormat] &&
dateTimeFormatOptions.time[userInterfaceTimeFormat]
? `${dateTimeFormatOptions.date[userInterfaceDateFormat]} ${dateTimeFormatOptions.time[userInterfaceTimeFormat]} z`
: 'llll';

export const longDate = (date, tz) => dateFormat(date, 'llll', tz);
return getFormattedDate(date, formatString, tz);
};

export const dateTimeWithTimeZone = (date, tz) =>
dateFormat(date, 'llll z', tz);
export const dateTimeWithTimeZone = (
date,
tz,
userInterfaceTimeFormat,
userInterfaceDateFormat,
) => {
const formatString =
dateTimeFormatOptions.date[userInterfaceDateFormat] &&
dateTimeFormatOptions.time[userInterfaceTimeFormat]
? `${dateTimeFormatOptions.date[userInterfaceDateFormat]} ${dateTimeFormatOptions.time[userInterfaceTimeFormat]} z`
: 'llll z';

// vim: set ts=2 sw=2 tw=80:
return getFormattedDate(date, formatString, tz);
};
96 changes: 85 additions & 11 deletions src/web/components/date/__tests__/datetime.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
*/

/* eslint-disable no-console */
import {describe, test, expect, testing} from '@gsa/testing';
import {
describe,
test,
expect,
testing,
beforeAll,
afterAll,
} from '@gsa/testing';

import Date from 'gmp/models/date';

Expand All @@ -13,10 +20,35 @@ import {rendererWith} from 'web/utils/testing';
import {setTimezone} from 'web/store/usersettings/actions';

import DateTime from '../datetime';
import {loadingActions} from 'web/store/usersettings/defaults/actions';

const getSetting = testing.fn().mockResolvedValue({});

const gmp = {
user: {
getSetting,
},
};

describe('DateTime render tests', () => {
let originalSetItem;

beforeAll(() => {
originalSetItem = localStorage.setItem;
localStorage.setItem = testing.fn();
});

afterAll(() => {
localStorage.setItem = originalSetItem;
});
test('should render nothing if date is undefined', () => {
const {render} = rendererWith({store: true});
const {render, store} = rendererWith({gmp, store: true});
store.dispatch(
loadingActions.success({
userinterfacetimeformat: {value: 12},
userinterfacedateformat: {value: 'wdmy'},
}),
);

const {element} = render(<DateTime />);

Expand All @@ -25,10 +57,16 @@ describe('DateTime render tests', () => {

test('should render nothing for invalid date', () => {
// deactivate console.warn for test
const consolewarn = console.warn;
const consoleWarn = console.warn;
console.warn = () => {};

const {render} = rendererWith({store: true});
const {render, store} = rendererWith({gmp, store: true});
store.dispatch(
loadingActions.success({
userinterfacetimeformat: {value: 12},
userinterfacedateformat: {value: 'wdmy'},
}),
);

const date = Date('foo');

Expand All @@ -38,19 +76,23 @@ describe('DateTime render tests', () => {

expect(element).toBeNull();

console.warn = consolewarn;
console.warn = consoleWarn;
});

test('should call formatter', () => {
const formatter = testing.fn().mockReturnValue('foo');
const {render, store} = rendererWith({store: true});

const {render, store} = rendererWith({gmp, store: true});

const date = Date('2019-01-01T12:00:00Z');

expect(date.isValid()).toEqual(true);

store.dispatch(setTimezone('CET'));

localStorage.setItem('userInterfaceTimeFormat', 12);
localStorage.setItem('userInterfaceDateFormat', 'wdmy');

const {baseElement} = render(
<DateTime date={date} formatter={formatter} />,
);
Expand All @@ -59,17 +101,49 @@ describe('DateTime render tests', () => {
expect(baseElement).toHaveTextContent('foo');
});

test('should render with default formatter', () => {
const {render, store} = rendererWith({store: true});
test.each([
[
'should render with default formatter',
{
userinterfacetimeformat: {value: undefined},
userinterfacedateformat: {value: undefined},
},
'Tue, Jan 1, 2019 1:00 PM CET',
],
[
'should render with 24 h and WeekDay, Month, Day, Year formatter',
{
userinterfacetimeformat: {value: 24},
userinterfacedateformat: {value: 'wmdy'},
},
'Tue, Jan 1, 2019 13:00 CET',
],
[
'should render with 12 h and WeekDay, Day, Month, Year formatter',
{
userinterfacetimeformat: {value: 12},
userinterfacedateformat: {value: 'wdmy'},
},
'Tue, 1 Jan 2019 1:00 PM CET',
],
])('%s', (_, settings, expectedText) => {
const {render, store} = rendererWith({gmp, store: true});

localStorage.setItem(
'userInterfaceTimeFormat',
settings.userinterfacetimeformat.value,
);
localStorage.setItem(
'userInterfaceDateFormat',
settings.userinterfacedateformat.value,
);

const date = Date('2019-01-01T12:00:00Z');

expect(date.isValid()).toEqual(true);

store.dispatch(setTimezone('CET'));

const {baseElement} = render(<DateTime date={date} />);

expect(baseElement).toHaveTextContent('Tue, Jan 1, 2019 1:00 PM CET');
expect(baseElement).toHaveTextContent(expectedText);
});
});
4 changes: 2 additions & 2 deletions src/web/hooks/__tests__/useUserSessionTimeout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import {describe, test, expect} from '@gsa/testing';

import {dateFormat} from 'gmp/locale/date';
import {getFormattedDate} from 'gmp/locale/date';
import date from 'gmp/models/date';

import {setSessionTimeout as setSessionTimeoutAction} from 'web/store/usersettings/actions';
Expand All @@ -21,7 +21,7 @@ const TestUserSessionTimeout = () => {
onClick={() => setSessionTimeout(date('2020-03-10'))}
onKeyDown={() => {}}
>
{dateFormat(sessionTimeout, 'DD-MM-YY')}
{getFormattedDate(sessionTimeout, 'DD-MM-YY')}
</button>
);
};
Expand Down
68 changes: 38 additions & 30 deletions src/web/pages/login/loginpage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,38 +94,46 @@ class LoginPage extends React.Component {
this.login(gmp.settings.guestUsername, gmp.settings.guestPassword);
}

login(username, password) {
async login(username, password) {
const {gmp} = this.props;

gmp.login(username, password).then(
data => {
const {locale, timezone, sessionTimeout} = data;

const {location, navigate} = this.props;

this.props.setTimezone(timezone);
this.props.setLocale(locale);
this.props.setSessionTimeout(sessionTimeout);
this.props.setUsername(username);
// must be set before changing the location
this.props.setIsLoggedIn(true);

if (
location &&
location.state &&
location.state.next &&
location.state.next !== location.pathname
) {
navigate(location.state.next, {replace: true});
} else {
navigate('/dashboards', {replace: true});
}
},
rej => {
log.error(rej);
this.setState({error: rej});
},
);
try {
const data = await gmp.login(username, password);

const {location, navigate} = this.props;
const {locale, timezone, sessionTimeout} = data;

this.props.setTimezone(timezone);
this.props.setLocale(locale);
this.props.setSessionTimeout(sessionTimeout);
this.props.setUsername(username);
// must be set before changing the location
this.props.setIsLoggedIn(true);

if (location?.state?.next && location.state.next !== location.pathname) {
navigate(location.state.next, {replace: true});
} else {
navigate('/dashboards', {replace: true});
}
} catch (error) {
log.error(error);
this.setState({error});
}

try {
const userSettings = await gmp.user.currentSettings();

localStorage.setItem(
'userInterfaceTimeFormat',
userSettings.data.userinterfacetimeformat.value,
);
localStorage.setItem(
'userInterfaceDateFormat',
userSettings.data.userinterfacedateformat.value,
);
} catch (error) {
log.error(error);
}
}

componentDidMount() {
Expand Down
Loading

0 comments on commit 532c646

Please sign in to comment.