Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix app header language flag doesn't set the user preference in BE #4132

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/gmp/commands/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,19 @@ export class UserCommand extends EntityCommand {
});
}

saveSetting(settingId, settingValue) {
log.debug(`Saving setting ${settingId} with value ${settingValue}`);
try {
return this.httpPost({
cmd: 'save_setting',
setting_id: settingId,
setting_value: settingValue,
});
} catch (error) {
log.warn(`Failed to save setting ${settingId}: ${error}`);
}
}

getReportComposerDefaults() {
return this.httpGet({
cmd: 'get_setting',
Expand Down
34 changes: 34 additions & 0 deletions src/web/components/structure/__tests__/languageswitch.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2024 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {describe, test, expect, testing} from '@gsa/testing';
import {setLocale} from 'web/store/usersettings/actions';
import {rendererWith, fireEvent, screen} from 'web/utils/testing';

import LanguageSwitch from 'web/components/structure/languageswitch';

const mockSaveSetting = testing.fn();
const mockSetLocale = testing.fn();

const gmp = {
user: {
saveSetting: () => mockSaveSetting(),
},
setLocale: () => mockSetLocale(),
};

describe('LanguageSwitch', () => {
test('should switch language and update settings', async () => {
const {render, store} = rendererWith({store: true, gmp});
store.dispatch(setLocale('en'));
const {getByRole} = render(<LanguageSwitch />);

const button = getByRole('button', {name: 'Switch language to German'});

fireEvent.click(button);

expect(screen.getByTitle('Switch language to English')).toBeVisible();
});
});
27 changes: 23 additions & 4 deletions src/web/components/structure/languageswitch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,52 @@

import {FlagDeIcon, FlagEnIcon} from '@greenbone/opensight-ui-components';
import {ActionIcon} from '@mantine/core';
import useGmp from 'web/hooks/useGmp';

import useLocale from 'web/hooks/useLocale';
import useTranslation from 'web/hooks/useTranslation';

const getNextLanguage = language => (language === 'en' ? 'de' : 'en');
const LANGUAGES = {
EN: 'en',
DE: 'de',
};

const SETTING_ID_LOCALE = '6765549a-934e-11e3-b358-406186ea4fc5';

const getNextLanguage = language =>
language === LANGUAGES.EN ? LANGUAGES.DE : LANGUAGES.EN;

const LanguageSwitch = () => {
const [language, changeLanguage] = useLocale();
const [_] = useTranslation();
const gmp = useGmp();

const nextLanguage = getNextLanguage(language);
const titles = {
en: _('Switch language to English'),
de: _('Switch language to German'),
};

const handleLanguageChange = () => {
changeLanguage(nextLanguage);
const handleLanguageChange = async () => {
try {
changeLanguage(nextLanguage);

await gmp.user.saveSetting(SETTING_ID_LOCALE, nextLanguage);

gmp.setLocale(nextLanguage);
} catch (error) {
throw new Error(error);
}
};

return (
<ActionIcon
variant="transparent"
onClick={handleLanguageChange}
title={titles[nextLanguage]}
color="neutral.0"
>
{language === 'en' ? <FlagEnIcon /> : <FlagDeIcon />}
{language === LANGUAGES.EN ? <FlagEnIcon /> : <FlagDeIcon />}
</ActionIcon>
);
};
Expand Down
22 changes: 18 additions & 4 deletions src/web/hooks/useLocale.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,30 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {useCallback} from 'react';
import {useEffect, useCallback} from 'react';
import {isDefined} from 'gmp/utils/identity';

import {useSelector, useDispatch} from 'react-redux';

import {setLocale as setGlobalLocale} from 'gmp/locale/lang';
import {
setLocale as setGlobalLocale,
getLocale as getGlobalLocal,
} from 'gmp/locale/lang';

import {setLocale} from 'web/store/usersettings/actions';
import {getLocale} from 'web/store/usersettings/selectors';

async function wait(ms = 0) {
new Promise(resolve => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
/**
* Hook to get current locale and allow to change it
*
* @returns Array of the current locale and a function to change the locale
* @returns {[string, function]} Current locale and a function to change it.
*/

const useLocale = () => {
const dispatch = useDispatch();
const currentLocale = useSelector(getLocale);
Expand All @@ -39,6 +44,15 @@ const useLocale = () => {
},
[currentLocale, dispatch],
);

// Effect to initialize the locale if it's not already defined
useEffect(() => {
if (!isDefined(currentLocale)) {
const locale = getGlobalLocal();
changeLocale(locale);
}
}, [currentLocale, changeLocale]);

return [currentLocale, changeLocale];
};

Expand Down
Loading