Skip to content

Commit

Permalink
refactor: evgeniy/92724/language settings improvements (#8176)
Browse files Browse the repository at this point in the history
* refactor: evgeniy/92724/language settings improvements

* fix: cursor button fix

* feat: same language menu usage for responsive

* fix: hide language icon while opening language menu

* refactor: review change, adding types and dependencies

* fix: changes from master missed

* fix: reading undefined error

* fix: duplicated properties

* fix: types duplicate

* chore: language-settings test

* refactor: menu-link store separately

* chore: menu-link test coverage

* refactor: test code structure

* refactor: link code

* refactor: remove unused code

* refactor: code readability

* refactor: variable usage

* refactor: variable usage

* refactor: review comments incorporating

* fix: test refactor with mockstore

* fix: missing mock

* fix: 🎨 incorporated deriv/util package

* fix: ⚡ refactored code

* feat: resolved code smells

* feat: resolved review comments

* feat: resolved review comments

* feat: resolved review comments

* fix: failing testcase

* fix: 🐛 missing import

* Trigger build

* chore: trigger build

* Merge branch 'master' into evgeniy/92724/language_settings_improvements

* chore: review comments incorporate

* refactor: types store alphabetically order

* refactor: types store alphabetically order

* refactor: menulink export fix

* chore: remove unused variable

* refactor: remove unused variable

* chore: trigger build

* fix: resolve conflicts

* fix: repeated fields

* chore: isExternalLink description

* chore: bootstrap

---------

Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”>
Co-authored-by: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com>
Co-authored-by: Matin shafiei <matin@deriv.com>
Co-authored-by: Likhith Kolayari <likhith@regentmarkets.com>
  • Loading branch information
5 people authored and vinu-deriv committed Oct 10, 2023
1 parent 36e3065 commit 37f4e3d
Show file tree
Hide file tree
Showing 24 changed files with 683 additions and 388 deletions.
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { isMobile, routes } from '@deriv/shared';
import LanguageSettings from '../language-settings';
import { mockStore, StoreProvider } from '@deriv/stores';

jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
isMobile: jest.fn(() => false),
}));

jest.mock('@deriv/translations', () => ({
...jest.requireActual('@deriv/translations'),
getAllowedLanguages: jest.fn(() => ({ lang_1: 'Test Lang 1', lang_2: 'Test Lang 2' })),
}));

jest.mock('@deriv/components', () => ({
...jest.requireActual('@deriv/components'),
Icon: jest.fn(() => <div>Flag Icon</div>),
}));

jest.mock('react-i18next', () => ({
...jest.requireActual('react-i18next'),
useTranslation: jest.fn(() => ({ i18n: { changeLanguage: jest.fn() } })),
}));

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
Redirect: jest.fn(() => <div>Redirect</div>),
}));

describe('LanguageSettings', () => {
const mockRootStore = mockStore({
common: {
current_language: 'lang_1',
},
});

const renderLanguageSettings = () => {
render(<LanguageSettings />, {
wrapper: ({ children }) => <StoreProvider store={mockRootStore}>{children}</StoreProvider>,
});
};

it('should render LanguageSettings', () => {
renderLanguageSettings();

expect(screen.getByText('Select Language')).toBeInTheDocument();

const flags_icons = screen.getAllByText('Flag Icon');
const lang_1 = screen.getByText('Test Lang 1');
const lang_2 = screen.getByText('Test Lang 2');

expect(flags_icons.length).toBe(2);
expect(lang_1).toBeInTheDocument();
expect(/(active)/i.test(lang_1.className)).toBeTruthy();
expect(lang_2).toBeInTheDocument();
expect(/(active)/i.test(lang_2.className)).toBeFalsy();
});

it('should trigger language change', () => {
renderLanguageSettings();

const lang_2 = screen.getByText('Test Lang 2');
userEvent.click(lang_2);

expect(mockRootStore.common.changeSelectedLanguage).toHaveBeenCalled();
});

it('should redirect for mobile', () => {
(isMobile as jest.Mock).mockReturnValue(true);
Object.defineProperty(window, 'location', {
configurable: true,
value: { pathname: routes.languages },
});

renderLanguageSettings();

expect(screen.queryByText('Select Language')).not.toBeInTheDocument();
expect(screen.getByText('Redirect')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,68 +1,40 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Button, DesktopWrapper } from '@deriv/components';
import { Redirect } from 'react-router-dom';
import { localize, getAllowedLanguages } from '@deriv/translations';
import { isMobile, routes } from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
import FormSubHeader from 'Components/form-sub-header';
import { Formik, FormikHandlers, FormikHelpers, FormikValues } from 'formik';
import FormFooter from 'Components/form-footer';
import LanguageRadioButton from 'Components/language-settings';
import { observer, useStore } from '@deriv/stores';

const LanguageSettings = observer(() => {
const { common } = useStore();
const { changeSelectedLanguage, current_language, isCurrentLanguage } = common;
const { i18n } = useTranslation();
const { changeSelectedLanguage, current_language } = common;

if (window.location.pathname === routes.languages && isMobile()) {
return <Redirect to={routes.traders_hub} />;
}

const allowed_language_keys: string[] = Object.keys(getAllowedLanguages());
const initial_values = { language_code: current_language };
return (
<Formik
initialValues={initial_values}
onSubmit={async values => {
const { language_code } = values;
await changeSelectedLanguage(language_code);
await i18n.changeLanguage?.(language_code);
}}
>
{({ handleSubmit, setFieldValue, values }: FormikHandlers & FormikHelpers<FormikValues> & FormikValues) => {
return (
<form onSubmit={handleSubmit} className='account-form account-form--language-settings'>
<div className='settings-language'>
<DesktopWrapper>
<FormSubHeader title={localize('Select Language')} />
</DesktopWrapper>
<div className='settings-language__language-container'>
{allowed_language_keys.map(language_key => {
return (
<LanguageRadioButton
key={language_key}
id={language_key}
language_code={language_key}
is_current_language={values.language_code === language_key}
name='language-radio-group'
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setFieldValue('language_code', event.target.value)
}
/>
);
})}
</div>
</div>
<FormFooter>
<Button
className='account-form__footer-btn'
type='submit'
data-testid={'submit-button'}
has_effect
text={localize('Submit')}
large
primary
is_disabled={isCurrentLanguage(values.language_code)}
/>
</FormFooter>
</form>
);
}}
</Formik>
<div className='settings-language'>
<FormSubHeader title={localize('Select Language')} />
<div className='settings-language__language-container'>
{allowed_language_keys.map(language_key => {
return (
<LanguageRadioButton
key={language_key}
id={language_key}
language_code={language_key}
is_current_language={current_language === language_key}
name='language-radio-group'
onChange={() => {
changeSelectedLanguage(language_key);
}}
/>
);
})}
</div>
</div>
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type TMobileDrawerSubmenu = {
submenu_icon?: string;
submenu_title?: string | React.ReactElement;
submenu_suffix_icon?: string;
route_config_path: string;
route_config_path?: string;
};

const SubMenu = ({
Expand Down Expand Up @@ -43,7 +43,9 @@ const SubMenu = ({
<Text
as='h3'
size='xs'
weight={window.location.pathname.startsWith(route_config_path) ? 'bold' : ''}
weight={
route_config_path && window.location.pathname.startsWith(route_config_path) ? 'bold' : ''
}
>
{submenu_title}
</Text>
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"@deriv/shared": "^1.0.0",
"@deriv/trader": "^3.8.0",
"@deriv/translations": "^1.0.0",
"@deriv/utils": "^1.0.0",
"@livechat/customer-sdk": "^2.0.4",
"acorn": "^6.1.1",
"babel-polyfill": "^6.26.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import MenuTitle from './menu-title';
import MobileLanguageMenu from './mobile-language-menu';

export { MenuTitle, MobileLanguageMenu };
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { observer, useStore } from '@deriv/stores';
import { Icon, Text } from '@deriv/components';
import { localize, Localize } from '@deriv/translations';

const MenuTitle = observer(() => {
const { common, ui } = useStore();
const { current_language } = common;
const { is_mobile_language_menu_open, setMobileLanguageMenuOpen } = ui;
return (
<React.Fragment>
<div>{localize('Menu')}</div>
<div
className='settings-language__language-button_wrapper'
onClick={() => {
if (!is_mobile_language_menu_open) {
setMobileLanguageMenuOpen(true);
}
}}
>
{!is_mobile_language_menu_open && (
<React.Fragment>
<Icon
icon={`IcFlag${current_language.replace('_', '-')}`}
data_testid='dt_icon'
className='ic-settings-language__icon'
size={22}
/>
<Text weight='bold' size='xxs'>
<Localize i18n_default_text={current_language} />
</Text>
</React.Fragment>
)}
</div>
</React.Fragment>
);
});

export default MenuTitle;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import classNames from 'classnames';
import React from 'react';
import { MobileDrawer } from '@deriv/components';
import { observer, useStore } from '@deriv/stores';
import { getAllowedLanguages, localize } from '@deriv/translations';
import { LanguageLink } from 'App/Components/Routes';

type TMobileLanguageMenu = {
expandSubMenu: (prop: boolean) => void;
toggleDrawer: () => void;
};

const MobileLanguageMenu = observer(({ expandSubMenu, toggleDrawer }: TMobileLanguageMenu) => {
const { common, ui } = useStore();
const { is_language_changing } = common;
const { is_mobile_language_menu_open, setMobileLanguageMenuOpen } = ui;
return (
<MobileDrawer.SubMenu
is_expanded={is_mobile_language_menu_open}
has_subheader
submenu_title={localize('Language')}
onToggle={is_expanded => {
expandSubMenu(is_expanded);
setMobileLanguageMenuOpen(false);
}}
submenu_toggle_class='dc-mobile-drawer__submenu-toggle--hidden'
>
<div
className={classNames('settings-language__language-container', {
'settings-language__language-container--disabled': is_language_changing,
})}
>
{Object.keys(getAllowedLanguages()).map(lang => (
<LanguageLink
key={lang}
icon_classname='settings-language__language-flag'
is_clickable
lang={lang}
toggleModal={() => {
toggleDrawer();
setMobileLanguageMenuOpen(false);
}}
/>
))}
</div>
</MobileDrawer.SubMenu>
);
});

export default MobileLanguageMenu;
Loading

0 comments on commit 37f4e3d

Please sign in to comment.