Skip to content

Commit

Permalink
umputun#10 localize auth panel
Browse files Browse the repository at this point in the history
  • Loading branch information
Mavrin committed Feb 18, 2020
1 parent 0ea9a48 commit f2d4d79
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 41 deletions.
19 changes: 10 additions & 9 deletions frontend/app/components/auth-panel/auth-panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { mount } from 'enzyme';
import { Button } from '@app/components/button';
import { User, PostInfo } from '@app/common/types';

import { Props, AuthPanel } from './auth-panel';
import { Props, AuthPanelWithIntl as AuthPanel } from './auth-panel';
import { IntlProvider } from 'react-intl';
import enMessages from '../../locales/en.json';

const DefaultProps: Partial<Props> = {
sort: '-score',
Expand All @@ -24,7 +25,7 @@ describe('<AuthPanel />', () => {
describe('For not authorized user', () => {
it('should render login form with google and github provider', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel {...(DefaultProps as Props)} user={null} />
</IntlProvider>
);
Expand All @@ -46,7 +47,7 @@ describe('<AuthPanel />', () => {
describe('sorting', () => {
it('should place selected provider first', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel
{...(DefaultProps as Props)}
providers={['google', 'github', 'yandex']}
Expand All @@ -68,7 +69,7 @@ describe('<AuthPanel />', () => {

it('should do nothing if provider not found', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel
{...(DefaultProps as Props)}
providers={['google', 'github', 'yandex']}
Expand All @@ -91,7 +92,7 @@ describe('<AuthPanel />', () => {

it('should render login form with google and github provider for read-only post', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel
{...(DefaultProps as Props)}
user={null}
Expand All @@ -116,7 +117,7 @@ describe('<AuthPanel />', () => {

it('should not render settings if there is no hidden users', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel
{...(DefaultProps as Props)}
user={null}
Expand All @@ -132,7 +133,7 @@ describe('<AuthPanel />', () => {

it('should render settings if there is some hidden users', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel
{...(DefaultProps as Props)}
user={null}
Expand All @@ -150,7 +151,7 @@ describe('<AuthPanel />', () => {
describe('For authorized user', () => {
it('should render info about current user', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel {...(DefaultProps as Props)} user={{ id: `john`, name: 'John' } as User} />
</IntlProvider>
);
Expand All @@ -167,7 +168,7 @@ describe('<AuthPanel />', () => {
describe('For admin user', () => {
it('should render admin action', () => {
const element = mount(
<IntlProvider locale="en">
<IntlProvider locale="en" messages={enMessages}>
<AuthPanel {...(DefaultProps as Props)} user={{ id: `test`, admin: true, name: 'John' } as User} />{' '}
</IntlProvider>
);
Expand Down
165 changes: 141 additions & 24 deletions frontend/app/components/auth-panel/auth-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { StoreState } from '@app/store';
import { ProviderState } from '@app/store/provider/reducers';
import { Dropdown, DropdownItem } from '@app/components/dropdown';
import { Button } from '@app/components/button';
import { FormattedMessage } from 'react-intl';
import { FormattedMessage, defineMessages, IntlShape, useIntl } from 'react-intl';

import { AnonymousLoginForm } from './__anonymous-login-form';
import { EmailLoginFormConnected } from './__email-login-form';
import { EmailLoginFormRef } from './__email-login-form/auth-panel__email-login-form';

export interface Props {
interface PropsWithoutIntl {
user: User | null;
hiddenUsers: StoreState['hiddenUsers'];
sort: Sorting;
Expand All @@ -38,13 +38,36 @@ export interface Props {
onBlockedUsersHide(): void;
}

export type Props = PropsWithoutIntl & { intl: IntlShape };

interface State {
isBlockedVisible: boolean;
anonymousUsernameInputValue: string;
threshold: number;
sortSelectFocused: boolean;
}

defineMessages({
'authPanel.other-provider': {
id: 'authPanel.other-provider',
defaultMessage: 'Other',
},
});

defineMessages({
'authPanel.anonymous-provider': {
id: 'authPanel.anonymous-provider',
defaultMessage: 'Anonymous',
},
});

defineMessages({
'authPanel.or-provider': {
id: 'authPanel.or-provider',
defaultMessage: 'or',
},
});

export class AuthPanel extends Component<Props, State> {
emailLoginRef = createRef<EmailLoginFormRef>();

Expand Down Expand Up @@ -171,7 +194,7 @@ export class AuthPanel extends Component<Props, State> {
{!isUserAnonymous && (
<DropdownItem>
<Button theme={theme} onClick={() => requestDeletion().then(onSignOut)}>
Request my data removal
<FormattedMessage id="authPanel.request-to-delete-data" defaultMessage="Request my data removal" />
</Button>
</DropdownItem>
)}
Expand All @@ -185,9 +208,13 @@ export class AuthPanel extends Component<Props, State> {

renderProvider = (provider: AuthProvider['name'], dropdown = false) => {
if (provider === 'anonymous') {
const anonymous = this.props.intl.formatMessage({
id: 'authPanel.anonymous-provider',
defaultMessage: 'authPanel.anonymous-provider',
});
return (
<Dropdown
title={PROVIDER_NAMES['anonymous']}
title={anonymous}
titleClass={dropdown ? 'auth-panel__dropdown-provider' : ''}
theme={this.props.theme}
>
Expand Down Expand Up @@ -235,8 +262,12 @@ export class AuthPanel extends Component<Props, State> {
};

renderOther = (providers: AuthProvider['name'][]) => {
const other = this.props.intl.formatMessage({
id: 'authPanel.other-provider',
defaultMessage: 'authPanel.other-provider',
});
return (
<Dropdown title="Other" theme={this.props.theme} onTitleClick={this.onEmailTitleClick}>
<Dropdown title={other} theme={this.props.theme} onTitleClick={this.onEmailTitleClick}>
{providers.map(provider => (
<DropdownItem>{this.renderProvider(provider, true)}</DropdownItem>
))}
Expand All @@ -261,13 +292,16 @@ export class AuthPanel extends Component<Props, State> {
})();

const isAboveThreshold = sortedProviders.length > threshold;

const or = this.props.intl.formatMessage({
id: 'authPanel.or-provider',
defaultMessage: 'authPanel.or-provider',
});
return (
<div className="auth-panel__column">
<FormattedMessage id="authPanel.login" defaultMessage="Login:" />{' '}
{!isAboveThreshold &&
sortedProviders.map((provider, i) => {
const comma = i === 0 ? '' : i === sortedProviders.length - 1 ? ' or ' : ', ';
const comma = i === 0 ? '' : i === sortedProviders.length - 1 ? ` ${or} ` : ', ';

return (
<span>
Expand All @@ -289,7 +323,7 @@ export class AuthPanel extends Component<Props, State> {
})}
{isAboveThreshold && (
<span>
{' or '}
{` ${or} `}
{this.renderOther(sortedProviders.slice(threshold - 1))}
</span>
)}
Expand All @@ -301,7 +335,10 @@ export class AuthPanel extends Component<Props, State> {
if (IS_STORAGE_AVAILABLE || !IS_THIRD_PARTY) return null;
return (
<div className="auth-panel__column">
Disable third-party cookies blocking to login or open comments in{' '}
<FormattedMessage
id="authPanel.disabled-cookies"
defaultMessage="Disable third-party cookies blocking to login or open comments in"
/>{' '}
<a
className="auth-panel__pseudo-link"
href={`${window.location.origin}/web/comments.html${window.location.search}`}
Expand All @@ -315,7 +352,11 @@ export class AuthPanel extends Component<Props, State> {

renderCookiesWarning = () => {
if (IS_STORAGE_AVAILABLE || IS_THIRD_PARTY) return null;
return <div className="auth-panel__column">Allow cookies to login and comment</div>;
return (
<div className="auth-panel__column">
<FormattedMessage id="authPanel.enable-cookies" defaultMessage="Allow cookies to login and comment" />
</div>
);
};

renderSettingsLabel = () => {
Expand All @@ -326,7 +367,11 @@ export class AuthPanel extends Component<Props, State> {
{...getHandleClickProps(() => this.toggleBlockedVisibility())}
role="link"
>
{this.state.isBlockedVisible ? 'Hide' : 'Show'} settings
{this.state.isBlockedVisible ? (
<FormattedMessage id="authPanel.hide-settings" defaultMessage="Hide settings" />
) : (
<FormattedMessage id="authPanel.show-settings" defaultMessage="Show settings" />
)}
</Button>
);
};
Expand All @@ -340,18 +385,22 @@ export class AuthPanel extends Component<Props, State> {
{...getHandleClickProps(() => this.toggleCommentsAvailability())}
role="link"
>
{isCommentsDisabled ? 'Enable' : 'Disable'} comments
{isCommentsDisabled ? (
<FormattedMessage id="authPanel.enable-comments" defaultMessage="Enable comments" />
) : (
<FormattedMessage id="authPanel.disable-comments" defaultMessage="Disable comments" />
)}
</Button>
);
};

renderSort = () => {
const { sort } = this.props;
const { sortSelectFocused } = this.state;
const sortArray = getSortArray(sort);
const sortArray = getSortArray(sort, this.props.intl);
return (
<span className="auth-panel__sort">
Sort by{' '}
<FormattedMessage id="commentSort.sort-by" defaultMessage="Sort by" />{' '}
<span className="auth-panel__select-label">
<span className={b('auth-panel__select-label-value', {}, { focused: sortSelectFocused })}>
{sortArray.find(x => 'selected' in x && x.selected!)!.label}
Expand Down Expand Up @@ -397,7 +446,11 @@ export class AuthPanel extends Component<Props, State> {

{isAdmin && ' • '}

{!isAdmin && read_only && <span className="auth-panel__readonly-label">Read-only</span>}
{!isAdmin && read_only && (
<span className="auth-panel__readonly-label">
<FormattedMessage id="authPanel.read-only" defaultMessage="Read-only" />
</span>
)}

{this.renderSort()}
</div>
Expand All @@ -406,43 +459,102 @@ export class AuthPanel extends Component<Props, State> {
}
}

function getSortArray(currentSort: Sorting) {
defineMessages({
'commentsSort.best': {
id: 'commentsSort.best',
defaultMessage: 'Best',
},
'commentsSort.worst': {
id: 'commentsSort.worst',
defaultMessage: 'Worst',
},
'commentsSort.newest': {
id: 'commentsSort.newest',
defaultMessage: 'Newest',
},
'commentsSort.oldest': {
id: 'commentsSort.oldest',
defaultMessage: 'Oldest',
},
'commentsSort.recently-updated': {
id: 'commentsSort.recently-updated',
defaultMessage: 'Recently updated',
},
'commentsSort.least-recently-updated': {
id: 'commentsSort.least-recently-updated',
defaultMessage: 'Least recently updated',
},
'commentsSort.most-controversial': {
id: 'commentsSort.most-controversial',
defaultMessage: 'Most controversial',
},
'commentsSort.least-controversial': {
id: 'commentsSort.least-controversial',
defaultMessage: 'Least controversial',
},
});

function getSortArray(currentSort: Sorting, intl: IntlShape) {
const sortArray: {
value: Sorting;
label: string;
selected?: boolean;
}[] = [
{
value: '-score',
label: 'Best',
label: intl.formatMessage({
id: 'commentsSort.best',
defaultMessage: 'commentsSort.best',
}),
},
{
value: '+score',
label: 'Worst',
label: intl.formatMessage({
id: 'commentsSort.worst',
defaultMessage: 'commentsSort.worst',
}),
},
{
value: '-time',
label: 'Newest',
label: intl.formatMessage({
id: 'commentsSort.newest',
defaultMessage: 'commentsSort.newest',
}),
},
{
value: '+time',
label: 'Oldest',
label: intl.formatMessage({
id: 'commentsSort.oldest',
defaultMessage: 'commentsSort.oldest',
}),
},
{
value: '-active',
label: 'Recently updated',
label: intl.formatMessage({
id: 'commentsSort.recently-updated',
defaultMessage: 'commentsSort.recently-updated',
}),
},
{
value: '+active',
label: 'Least recently updated',
label: intl.formatMessage({
id: 'commentsSort.least-recently-updated',
defaultMessage: 'commentsSort.least-recently-updated',
}),
},
{
value: '-controversy',
label: 'Most controversial',
label: intl.formatMessage({
id: 'commentsSort.most-controversial',
defaultMessage: 'commentsSort.most-controversial',
}),
},
{
value: '+controversy',
label: 'Least controversial',
label: intl.formatMessage({
id: 'commentsSort.least-controversial',
defaultMessage: 'commentsSort.least-controversial',
}),
},
];

Expand All @@ -454,3 +566,8 @@ function getSortArray(currentSort: Sorting) {
return sort;
});
}

export const AuthPanelWithIntl = (props: PropsWithoutIntl) => {
const intl = useIntl();
return <AuthPanel intl={intl} {...props} />;
};
Loading

0 comments on commit f2d4d79

Please sign in to comment.