@jetbrains/ring-ui 5.0.138 → 5.0.139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/auth/auth__core.js +10 -10
- package/components/header/profile.d.ts +2 -53
- package/components/header/profile.js +8 -8
- package/components/i18n/README.md +43 -0
- package/components/i18n/i18n-context.d.ts +12 -53
- package/components/i18n/i18n-context.js +14 -3
- package/components/i18n/i18n.d.ts +6 -3
- package/components/i18n/i18n.js +18 -0
- package/components/input/input.js +2 -2
- package/components/message/message.js +5 -3
- package/components/pager/pager.d.ts +2 -53
- package/components/pager/pager.js +9 -8
- package/components/query-assist/query-assist.js +5 -5
- package/components/select/select.js +3 -3
- package/components/select/select__filter.js +1 -1
- package/components/user-agreement/user-agreement.js +8 -8
- package/components/user-card/card.d.ts +2 -53
- package/components/user-card/card.js +13 -11
- package/dist/_helpers/card.js +15 -11
- package/dist/_helpers/select__filter.js +5 -2
- package/dist/auth/auth__core.js +10 -11
- package/dist/header/profile.d.ts +2 -53
- package/dist/header/profile.js +13 -8
- package/dist/i18n/i18n-context.d.ts +12 -53
- package/dist/i18n/i18n-context.js +22 -4
- package/dist/i18n/i18n.d.ts +6 -3
- package/dist/i18n/i18n.js +23 -1
- package/dist/input/input.js +32 -26
- package/dist/link/link.js +1 -1
- package/dist/message/message.js +39 -31
- package/dist/pager/pager.d.ts +2 -53
- package/dist/pager/pager.js +14 -8
- package/dist/query-assist/query-assist.js +90 -81
- package/dist/select/select.js +8 -5
- package/dist/user-agreement/user-agreement.js +39 -33
- package/dist/user-card/card.d.ts +2 -53
- package/package.json +14 -14
|
@@ -2,7 +2,7 @@ import { fixUrl, getAbsoluteBaseURL } from '../global/url';
|
|
|
2
2
|
import Listeners from '../global/listeners';
|
|
3
3
|
import HTTP from '../http/http';
|
|
4
4
|
import promiseWithTimeout from '../global/promise-with-timeout';
|
|
5
|
-
import { getTranslations } from '../i18n/i18n';
|
|
5
|
+
import { getTranslations, getTranslationsWithFallback, translate } from '../i18n/i18n';
|
|
6
6
|
import AuthStorage from './storage';
|
|
7
7
|
import AuthResponseParser from './response-parser';
|
|
8
8
|
import AuthRequestBuilder from './request-builder';
|
|
@@ -120,7 +120,7 @@ class Auth {
|
|
|
120
120
|
}
|
|
121
121
|
this._backgroundFlow = new BackgroundFlow(this._requestBuilder, this._storage, backgroundRefreshTimeout);
|
|
122
122
|
if (this.config.EmbeddedLoginFlow) {
|
|
123
|
-
this._embeddedFlow = new this.config.EmbeddedLoginFlow(this._requestBuilder, this._storage, this.config.translations ??
|
|
123
|
+
this._embeddedFlow = new this.config.EmbeddedLoginFlow(this._requestBuilder, this._storage, this.config.translations ?? getTranslationsWithFallback());
|
|
124
124
|
}
|
|
125
125
|
const API_BASE = this.config.serverUri + Auth.API_PATH;
|
|
126
126
|
const fetchConfig = config.fetchCredentials
|
|
@@ -540,7 +540,6 @@ class Auth {
|
|
|
540
540
|
}
|
|
541
541
|
_showUserChangedDialog({ newUser, onApply, onPostpone }) {
|
|
542
542
|
const { translations } = this.config;
|
|
543
|
-
const actualTranslations = translations ?? getTranslations();
|
|
544
543
|
this._createInitDeferred();
|
|
545
544
|
const done = () => {
|
|
546
545
|
this._initDeferred?.resolve?.();
|
|
@@ -549,14 +548,14 @@ class Auth {
|
|
|
549
548
|
};
|
|
550
549
|
const hide = this._authDialogService?.({
|
|
551
550
|
...this._service,
|
|
552
|
-
title:
|
|
551
|
+
title: translations?.youHaveLoggedInAs ?? translate('youHaveLoggedInAs').
|
|
553
552
|
replace('%userName%', newUser.name ?? '').
|
|
554
553
|
replace('{{userName}}', newUser.name ?? ''),
|
|
555
|
-
loginCaption:
|
|
556
|
-
loginToCaption:
|
|
557
|
-
confirmLabel:
|
|
558
|
-
tryAgainLabel:
|
|
559
|
-
cancelLabel:
|
|
554
|
+
loginCaption: translations?.login ?? translate('login'),
|
|
555
|
+
loginToCaption: translations?.loginTo ?? translate('loginTo'),
|
|
556
|
+
confirmLabel: translations?.applyChange ?? translate('applyChange'),
|
|
557
|
+
tryAgainLabel: translations?.tryAgainLabel ?? translate('tryAgainLabel'),
|
|
558
|
+
cancelLabel: translations?.postpone ?? translate('postpone'),
|
|
560
559
|
onConfirm: () => {
|
|
561
560
|
done();
|
|
562
561
|
onApply();
|
|
@@ -617,7 +616,8 @@ class Auth {
|
|
|
617
616
|
reject(new Error('Auth(@jetbrains/ring-ui): postponed by user'));
|
|
618
617
|
};
|
|
619
618
|
const hide = onBackendDown({
|
|
620
|
-
onCheckAgain, onPostpone, backendError,
|
|
619
|
+
onCheckAgain, onPostpone, backendError,
|
|
620
|
+
translations: translations ?? getTranslationsWithFallback()
|
|
621
621
|
});
|
|
622
622
|
window.addEventListener('online', onCheckAgain);
|
|
623
623
|
function networkWatchdog() {
|
|
@@ -67,59 +67,8 @@ export default class Profile extends PureComponent<ProfileProps> {
|
|
|
67
67
|
renderGuest: PropTypes.Requireable<(...args: any[]) => any>;
|
|
68
68
|
};
|
|
69
69
|
static defaultProps: ProfileProps;
|
|
70
|
-
static contextType: React.Context<
|
|
71
|
-
|
|
72
|
-
logout: string;
|
|
73
|
-
loginTo: string;
|
|
74
|
-
ok: string;
|
|
75
|
-
cancel: string;
|
|
76
|
-
tryAgainLabel: string;
|
|
77
|
-
postpone: string;
|
|
78
|
-
youHaveLoggedInAs: string;
|
|
79
|
-
applyChange: string;
|
|
80
|
-
backendIsNotAvailable: string;
|
|
81
|
-
checkAgain: string;
|
|
82
|
-
nothingHappensLink: string;
|
|
83
|
-
errorMessage: string;
|
|
84
|
-
applyChangedUser: string;
|
|
85
|
-
profile: string;
|
|
86
|
-
switchUser: string;
|
|
87
|
-
addFirstDate: string;
|
|
88
|
-
addSecondDate: string;
|
|
89
|
-
addTime: string;
|
|
90
|
-
selectName: string;
|
|
91
|
-
setDate: string;
|
|
92
|
-
setDateTime: string;
|
|
93
|
-
setPeriod: string;
|
|
94
|
-
clear: string;
|
|
95
|
-
gotIt: string;
|
|
96
|
-
dismiss: string;
|
|
97
|
-
perPage: string;
|
|
98
|
-
firstPage: string;
|
|
99
|
-
lastPage: string;
|
|
100
|
-
nextPage: string;
|
|
101
|
-
previousPage: string;
|
|
102
|
-
searchTitle: string;
|
|
103
|
-
clearTitle: string;
|
|
104
|
-
userAgreement: string;
|
|
105
|
-
accept: string;
|
|
106
|
-
decline: string;
|
|
107
|
-
close: string;
|
|
108
|
-
scrollToAccept: string;
|
|
109
|
-
remindLater: string;
|
|
110
|
-
filterItems: string;
|
|
111
|
-
selectOption: string;
|
|
112
|
-
progress: string;
|
|
113
|
-
loading: string;
|
|
114
|
-
noOptionsFound: string;
|
|
115
|
-
banned: string;
|
|
116
|
-
online: string;
|
|
117
|
-
offline: string;
|
|
118
|
-
copyToClipboard: string;
|
|
119
|
-
copiedToClipboard: string;
|
|
120
|
-
copingToClipboardError: string;
|
|
121
|
-
unverified: string;
|
|
122
|
-
}>;
|
|
70
|
+
static contextType: React.Context<import("../i18n/i18n-context").I18nContextProps>;
|
|
71
|
+
context: React.ContextType<typeof Profile.contextType>;
|
|
123
72
|
static Size: typeof Size;
|
|
124
73
|
render(): string | number | boolean | JSX.Element | React.ReactFragment | null | undefined;
|
|
125
74
|
}
|
|
@@ -51,9 +51,9 @@ class Profile extends PureComponent {
|
|
|
51
51
|
renderPopupItems: items => items,
|
|
52
52
|
size: Size.Size32,
|
|
53
53
|
renderGuest: ({ loading, onLogin, className, translations }) => (<I18nContext.Consumer>
|
|
54
|
-
{
|
|
54
|
+
{({ translate }) => (<div className={classNames(styles.profileEmpty, className)}>
|
|
55
55
|
<Button primary data-test="ring-header-login-button" disabled={loading} loader={loading} onClick={onLogin}>
|
|
56
|
-
{translations?.login ??
|
|
56
|
+
{translations?.login ?? translate('login')}
|
|
57
57
|
</Button>
|
|
58
58
|
</div>)}
|
|
59
59
|
</I18nContext.Consumer>)
|
|
@@ -62,7 +62,7 @@ class Profile extends PureComponent {
|
|
|
62
62
|
static Size = Size;
|
|
63
63
|
render() {
|
|
64
64
|
const { className, closeOnSelect, hasUpdates, onLogout, user, profileUrl, LinkComponent, onSwitchUser, renderPopupItems, onRevertPostponement, showApplyChangedUser, showLogIn, showLogOut, showSwitchUser, renderGuest, translations, size, round, loading, onLogin, ...props } = this.props;
|
|
65
|
-
const
|
|
65
|
+
const { translate } = this.context;
|
|
66
66
|
if (!user) {
|
|
67
67
|
return (<div {...props} className={classNames(styles.profileEmpty, className)}>
|
|
68
68
|
<Avatar size={size} round={round}/>
|
|
@@ -80,32 +80,32 @@ class Profile extends PureComponent {
|
|
|
80
80
|
const items = [
|
|
81
81
|
showApplyChangedUser && {
|
|
82
82
|
rgItemType,
|
|
83
|
-
label: translations?.applyChangedUser ??
|
|
83
|
+
label: translations?.applyChangedUser ?? translate('applyChangedUser'),
|
|
84
84
|
className: styles.profileMenuItem,
|
|
85
85
|
onClick: onRevertPostponement
|
|
86
86
|
},
|
|
87
87
|
showLogIn && {
|
|
88
88
|
rgItemType,
|
|
89
|
-
label: translations?.login ??
|
|
89
|
+
label: translations?.login ?? translate('login'),
|
|
90
90
|
className: styles.profileMenuItem,
|
|
91
91
|
onClick: onRevertPostponement
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
rgItemType: PopupMenu.ListProps.Type.LINK,
|
|
95
|
-
label: translations?.profile ??
|
|
95
|
+
label: translations?.profile ?? translate('profile'),
|
|
96
96
|
target: '_self',
|
|
97
97
|
href: profileUrl,
|
|
98
98
|
LinkComponent
|
|
99
99
|
},
|
|
100
100
|
showSwitchUser && {
|
|
101
101
|
rgItemType,
|
|
102
|
-
label: translations?.switchUser ??
|
|
102
|
+
label: translations?.switchUser ?? translate('switchUser'),
|
|
103
103
|
className: styles.profileMenuItem,
|
|
104
104
|
onClick: onSwitchUser
|
|
105
105
|
},
|
|
106
106
|
showLogOut && {
|
|
107
107
|
rgItemType,
|
|
108
|
-
label: translations?.logout ??
|
|
108
|
+
label: translations?.logout ?? translate('logout'),
|
|
109
109
|
onClick: onLogout
|
|
110
110
|
}
|
|
111
111
|
].filter(isTruthy);
|
|
@@ -1,3 +1,46 @@
|
|
|
1
1
|
This is localisation layer, that allows to translate the app into different languages.
|
|
2
2
|
|
|
3
3
|
All messages should be stored in a messages.json, using that format https://www.i18next.com/misc/json-format#i18next-json-v4
|
|
4
|
+
|
|
5
|
+
### How to use
|
|
6
|
+
|
|
7
|
+
1. Using your project i18n tooling, construct an object with localised messages, like:
|
|
8
|
+
```
|
|
9
|
+
// You can use https://ttag.js.org/ for example:
|
|
10
|
+
const localised = {
|
|
11
|
+
login: t`Log in`,
|
|
12
|
+
...
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. Pass it to i18n singleton, using `setTranslations`. That would provide localisation to non-react components, like Auth.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
// Your messages object should have localised strings at that moment
|
|
20
|
+
const localised = {
|
|
21
|
+
login: 'Inloggen',
|
|
22
|
+
...
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setTranslations(localised);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. Add I18nContextHolder into your root React tree. If you replace "localised" object with another one, consumers would be updated automatically.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
<I18nContextHolder messages={localised}>
|
|
32
|
+
<App />
|
|
33
|
+
</I18nContextHolder>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Utilities
|
|
39
|
+
|
|
40
|
+
There is some ways to automate strings extraction from messages.json. You can do:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
npx i18next-conv -s messages.json -t messages.pot -l en --ctxSeparator "|" --compatibilityJSON v4
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
And get a .pot file, which you can merge with your other sources
|
|
@@ -1,54 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
nothingHappensLink: string;
|
|
15
|
-
errorMessage: string;
|
|
16
|
-
applyChangedUser: string;
|
|
17
|
-
profile: string;
|
|
18
|
-
switchUser: string;
|
|
19
|
-
addFirstDate: string;
|
|
20
|
-
addSecondDate: string;
|
|
21
|
-
addTime: string;
|
|
22
|
-
selectName: string;
|
|
23
|
-
setDate: string;
|
|
24
|
-
setDateTime: string;
|
|
25
|
-
setPeriod: string;
|
|
26
|
-
clear: string;
|
|
27
|
-
gotIt: string;
|
|
28
|
-
dismiss: string;
|
|
29
|
-
perPage: string;
|
|
30
|
-
firstPage: string;
|
|
31
|
-
lastPage: string;
|
|
32
|
-
nextPage: string;
|
|
33
|
-
previousPage: string;
|
|
34
|
-
searchTitle: string;
|
|
35
|
-
clearTitle: string;
|
|
36
|
-
userAgreement: string;
|
|
37
|
-
accept: string;
|
|
38
|
-
decline: string;
|
|
39
|
-
close: string;
|
|
40
|
-
scrollToAccept: string;
|
|
41
|
-
remindLater: string;
|
|
42
|
-
filterItems: string;
|
|
43
|
-
selectOption: string;
|
|
44
|
-
progress: string;
|
|
45
|
-
loading: string;
|
|
46
|
-
noOptionsFound: string;
|
|
47
|
-
banned: string;
|
|
48
|
-
online: string;
|
|
49
|
-
offline: string;
|
|
50
|
-
copyToClipboard: string;
|
|
51
|
-
copiedToClipboard: string;
|
|
52
|
-
copingToClipboardError: string;
|
|
53
|
-
unverified: string;
|
|
54
|
-
}>;
|
|
2
|
+
import { type Messages } from './i18n';
|
|
3
|
+
export interface I18nContextProps {
|
|
4
|
+
translate(key: keyof Messages): string;
|
|
5
|
+
messages: Messages;
|
|
6
|
+
}
|
|
7
|
+
export declare const I18nContext: React.Context<I18nContextProps>;
|
|
8
|
+
interface I18nContextHolderProps {
|
|
9
|
+
messages: Messages;
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare const I18nContextHolder: React.FC<I18nContextHolderProps>;
|
|
13
|
+
export {};
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { getTranslations } from './i18n';
|
|
3
|
-
export const I18nContext = React.createContext(
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { getTranslations, setTranslations, translate } from './i18n';
|
|
3
|
+
export const I18nContext = React.createContext({
|
|
4
|
+
messages: getTranslations(),
|
|
5
|
+
translate
|
|
6
|
+
});
|
|
7
|
+
export const I18nContextHolder = ({ children, messages }) => {
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
setTranslations(messages);
|
|
10
|
+
}, [messages]);
|
|
11
|
+
return (<I18nContext.Provider value={{ messages, translate }}>
|
|
12
|
+
{children}
|
|
13
|
+
</I18nContext.Provider>);
|
|
14
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import defaultMessages from './messages.json';
|
|
2
|
-
export type
|
|
2
|
+
export type MessagesStrict = typeof defaultMessages;
|
|
3
|
+
export type Messages = Partial<MessagesStrict>;
|
|
3
4
|
export declare function setTranslations(newMessages: Messages): void;
|
|
4
|
-
export declare function getTranslations(): {
|
|
5
|
+
export declare function getTranslations(): Partial<{
|
|
5
6
|
login: string;
|
|
6
7
|
logout: string;
|
|
7
8
|
loginTo: string;
|
|
@@ -53,4 +54,6 @@ export declare function getTranslations(): {
|
|
|
53
54
|
copiedToClipboard: string;
|
|
54
55
|
copingToClipboardError: string;
|
|
55
56
|
unverified: string;
|
|
56
|
-
}
|
|
57
|
+
}>;
|
|
58
|
+
export declare function getTranslationsWithFallback(): MessagesStrict;
|
|
59
|
+
export declare function translate(key: keyof MessagesStrict): string;
|
package/components/i18n/i18n.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import defaultMessages from './messages.json';
|
|
2
2
|
let messages = defaultMessages;
|
|
3
|
+
const warned = new Set();
|
|
4
|
+
function warnMissedKeyOnce(key) {
|
|
5
|
+
if (warned.has(key)) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
warned.add(key);
|
|
9
|
+
// eslint-disable-next-line no-console
|
|
10
|
+
console.warn(`Missing localisation for key "${key}"`);
|
|
11
|
+
}
|
|
3
12
|
export function setTranslations(newMessages) {
|
|
4
13
|
messages = newMessages;
|
|
5
14
|
}
|
|
6
15
|
export function getTranslations() {
|
|
7
16
|
return messages;
|
|
8
17
|
}
|
|
18
|
+
export function getTranslationsWithFallback() {
|
|
19
|
+
return { ...defaultMessages, ...messages };
|
|
20
|
+
}
|
|
21
|
+
export function translate(key) {
|
|
22
|
+
if (!(key in messages)) {
|
|
23
|
+
warnMissedKeyOnce(key);
|
|
24
|
+
}
|
|
25
|
+
return messages[key] ?? defaultMessages[key];
|
|
26
|
+
}
|
|
@@ -119,14 +119,14 @@ class Input extends PureComponent {
|
|
|
119
119
|
'data-enabled-shortcuts': Array.isArray(enableShortcuts) ? enableShortcuts.join(',') : null
|
|
120
120
|
};
|
|
121
121
|
return (<I18nContext.Consumer>
|
|
122
|
-
{
|
|
122
|
+
{({ translate }) => (<div className={classes} data-test="ring-input">
|
|
123
123
|
{label && (<InputLabel htmlFor={this.getId()} disabled={disabled} label={label}/>)}
|
|
124
124
|
<div className={styles.container}>
|
|
125
125
|
{icon && <Icon glyph={icon} className={styles.icon}/>}
|
|
126
126
|
{multiline
|
|
127
127
|
? (<textarea onChange={this.handleTextareaChange} rows={1} {...commonProps} {...restProps}/>)
|
|
128
128
|
: (<input onChange={this.handleInputChange} {...commonProps} {...restProps}/>)}
|
|
129
|
-
{clearable && !disabled && (<Button title={
|
|
129
|
+
{clearable && !disabled && (<Button title={translations?.clear ?? translate('clear')} data-test="ring-input-clear" className={styles.clear} icon={closeIcon} onClick={this.clear}/>)}
|
|
130
130
|
{afterInput}
|
|
131
131
|
</div>
|
|
132
132
|
{error && <div className={styles.errorText}>{error}</div>}
|
|
@@ -94,7 +94,7 @@ class Message extends Component {
|
|
|
94
94
|
: this.props.directions;
|
|
95
95
|
const { direction } = this.state;
|
|
96
96
|
return (<I18nContext.Consumer>
|
|
97
|
-
{
|
|
97
|
+
{({ translate }) => (<WithThemeClasses theme={theme}>
|
|
98
98
|
{themeClasses => (<Popup ref={this.popupRef} hidden={false} directions={popupDirections} className={classNames(classes, themeClasses)} offset={UNIT * 2} onDirectionChange={this._onDirectionChange} {...popupProps}>
|
|
99
99
|
<ThemeProvider theme={theme} passToPopups>
|
|
100
100
|
{direction && (<div className={tailClasses} style={getTailOffsets(this.getTailOffset())[direction]}/>)}
|
|
@@ -102,8 +102,10 @@ class Message extends Component {
|
|
|
102
102
|
{icon && <Icon className={styles.icon} glyph={icon}/>}
|
|
103
103
|
{title && <h1 data-test="rgMessageTitle" className={styles.title}>{title}</h1>}
|
|
104
104
|
{children && <div className={styles.description}>{children}</div>}
|
|
105
|
-
{(onClose || buttonProps) && (<Button className={styles.button} onClick={onClose} primary {...buttonProps}>{
|
|
106
|
-
{onDismiss && (<Button onClick={onDismiss} text>
|
|
105
|
+
{(onClose || buttonProps) && (<Button className={styles.button} onClick={onClose} primary {...buttonProps}>{translations?.gotIt ?? translate('gotIt')}</Button>)}
|
|
106
|
+
{onDismiss && (<Button onClick={onDismiss} text>
|
|
107
|
+
{translations?.dismiss ?? translate('dismiss')}
|
|
108
|
+
</Button>)}
|
|
107
109
|
</ThemeProvider>
|
|
108
110
|
</Popup>)}
|
|
109
111
|
</WithThemeClasses>)}
|
|
@@ -45,59 +45,8 @@ export default class Pager extends PureComponent<PagerProps> {
|
|
|
45
45
|
onPageSizeChange: () => void;
|
|
46
46
|
onLoadPage: () => void;
|
|
47
47
|
};
|
|
48
|
-
static contextType: React.Context<
|
|
49
|
-
|
|
50
|
-
logout: string;
|
|
51
|
-
loginTo: string;
|
|
52
|
-
ok: string;
|
|
53
|
-
cancel: string;
|
|
54
|
-
tryAgainLabel: string;
|
|
55
|
-
postpone: string;
|
|
56
|
-
youHaveLoggedInAs: string;
|
|
57
|
-
applyChange: string;
|
|
58
|
-
backendIsNotAvailable: string;
|
|
59
|
-
checkAgain: string;
|
|
60
|
-
nothingHappensLink: string;
|
|
61
|
-
errorMessage: string;
|
|
62
|
-
applyChangedUser: string;
|
|
63
|
-
profile: string;
|
|
64
|
-
switchUser: string;
|
|
65
|
-
addFirstDate: string;
|
|
66
|
-
addSecondDate: string;
|
|
67
|
-
addTime: string;
|
|
68
|
-
selectName: string;
|
|
69
|
-
setDate: string;
|
|
70
|
-
setDateTime: string;
|
|
71
|
-
setPeriod: string;
|
|
72
|
-
clear: string;
|
|
73
|
-
gotIt: string;
|
|
74
|
-
dismiss: string;
|
|
75
|
-
perPage: string;
|
|
76
|
-
firstPage: string;
|
|
77
|
-
lastPage: string;
|
|
78
|
-
nextPage: string;
|
|
79
|
-
previousPage: string;
|
|
80
|
-
searchTitle: string;
|
|
81
|
-
clearTitle: string;
|
|
82
|
-
userAgreement: string;
|
|
83
|
-
accept: string;
|
|
84
|
-
decline: string;
|
|
85
|
-
close: string;
|
|
86
|
-
scrollToAccept: string;
|
|
87
|
-
remindLater: string;
|
|
88
|
-
filterItems: string;
|
|
89
|
-
selectOption: string;
|
|
90
|
-
progress: string;
|
|
91
|
-
loading: string;
|
|
92
|
-
noOptionsFound: string;
|
|
93
|
-
banned: string;
|
|
94
|
-
online: string;
|
|
95
|
-
offline: string;
|
|
96
|
-
copyToClipboard: string;
|
|
97
|
-
copiedToClipboard: string;
|
|
98
|
-
copingToClipboardError: string;
|
|
99
|
-
unverified: string;
|
|
100
|
-
}>;
|
|
48
|
+
static contextType: React.Context<import("../i18n/i18n-context").I18nContextProps>;
|
|
49
|
+
context: React.ContextType<typeof Pager.contextType>;
|
|
101
50
|
getSelectOptions(): {
|
|
102
51
|
selected: SelectItem<PagerSizeItem> | undefined;
|
|
103
52
|
data: SelectItem<PagerSizeItem>[];
|
|
@@ -33,10 +33,10 @@ class Pager extends PureComponent {
|
|
|
33
33
|
static contextType = I18nContext;
|
|
34
34
|
getSelectOptions() {
|
|
35
35
|
const { pageSize, pageSizes } = this.props;
|
|
36
|
-
const
|
|
36
|
+
const { translate } = this.context;
|
|
37
37
|
const data = pageSizes.map(size => ({
|
|
38
38
|
key: size,
|
|
39
|
-
label: `${size} ${
|
|
39
|
+
label: `${size} ${this.props.translations?.perPage ?? translate('perPage')}`
|
|
40
40
|
}));
|
|
41
41
|
const selected = data.find(it => it.key === pageSize);
|
|
42
42
|
return { selected, data };
|
|
@@ -99,14 +99,14 @@ class Pager extends PureComponent {
|
|
|
99
99
|
</div>);
|
|
100
100
|
}
|
|
101
101
|
getPagerLinks() {
|
|
102
|
-
const
|
|
102
|
+
const { translate } = this.context;
|
|
103
103
|
const prevLinkAvailable = this.props.currentPage !== 1;
|
|
104
104
|
const nextLinkAvailable = this.props.openTotal ||
|
|
105
105
|
this.props.currentPage !== this.getTotalPages();
|
|
106
106
|
const nextIcon = (<Icon glyph={chevronRightIcon} key="icon"/>);
|
|
107
107
|
const prevIcon = (<Icon glyph={chevronLeftIcon} key="icon"/>);
|
|
108
|
-
const prevText =
|
|
109
|
-
const nextText =
|
|
108
|
+
const prevText = this.props.translations?.previousPage ?? translate('previousPage');
|
|
109
|
+
const nextText = this.props.translations?.nextPage ?? translate('nextPage');
|
|
110
110
|
const nextLinkContent = (WrapText) => [
|
|
111
111
|
<span key="text"><WrapText>{nextText}</WrapText></span>,
|
|
112
112
|
nextIcon
|
|
@@ -145,7 +145,7 @@ class Pager extends PureComponent {
|
|
|
145
145
|
getPagerContent() {
|
|
146
146
|
const { currentPage, visiblePagesLimit } = this.props;
|
|
147
147
|
const totalPages = this.getTotalPages();
|
|
148
|
-
const
|
|
148
|
+
const { translate } = this.context;
|
|
149
149
|
if (totalPages < this.props.currentPage) {
|
|
150
150
|
this.props.onPageChange?.(totalPages);
|
|
151
151
|
}
|
|
@@ -180,7 +180,8 @@ class Pager extends PureComponent {
|
|
|
180
180
|
{this.getPagerLinks()}
|
|
181
181
|
|
|
182
182
|
<ButtonToolbar>
|
|
183
|
-
{start > 1 &&
|
|
183
|
+
{start > 1 &&
|
|
184
|
+
this.getButton(1, this.props.translations?.firstPage ?? translate('firstPage'))}
|
|
184
185
|
|
|
185
186
|
<ButtonGroup>
|
|
186
187
|
{start > 1 && this.getButton(start - 1, '...')}
|
|
@@ -192,7 +193,7 @@ class Pager extends PureComponent {
|
|
|
192
193
|
{end === totalPages && this.props.openTotal && (<Button href={this.generateHref(end + 1)} disabled={this.props.loader} {...this.getClickProps(this.handleLoadMore(end + 1))}>{'...'}</Button>)}
|
|
193
194
|
</ButtonGroup>
|
|
194
195
|
|
|
195
|
-
{lastPageButtonAvailable && this.getButton(this.props.openTotal ? -1 : totalPages,
|
|
196
|
+
{lastPageButtonAvailable && this.getButton(this.props.openTotal ? -1 : totalPages, this.props.translations?.lastPage ?? translate('lastPage'))}
|
|
196
197
|
</ButtonToolbar>
|
|
197
198
|
|
|
198
199
|
{this.getPageSizeSelector()}
|
|
@@ -773,7 +773,7 @@ class QueryAssist extends Component {
|
|
|
773
773
|
const renderClear = this.props.clear && !!this.state.query;
|
|
774
774
|
if (renderClear) {
|
|
775
775
|
actions.push(<I18nContext.Consumer key={'clearAction'}>
|
|
776
|
-
{
|
|
776
|
+
{({ translate }) => (<Button icon={closeIcon} className={styles.clear} title={this.props.translations?.clearTitle ?? translate('clearTitle')} ref={this.clearRef} onClick={this.clearQuery} data-test="query-assist-clear-icon"/>)}
|
|
777
777
|
</I18nContext.Consumer>);
|
|
778
778
|
}
|
|
779
779
|
return actions;
|
|
@@ -803,10 +803,10 @@ class QueryAssist extends Component {
|
|
|
803
803
|
});
|
|
804
804
|
return (<ControlsHeightContext.Provider value={ControlsHeight.M}>
|
|
805
805
|
<I18nContext.Consumer>
|
|
806
|
-
{
|
|
806
|
+
{({ translate }) => (<div data-test={dataTests('ring-query-assist', dataTest)} className={containerClasses} role="presentation" ref={this.nodeRef}>
|
|
807
807
|
{this.state.shortcuts && (<Shortcuts map={this.shortcutsMap} scope={this.shortcutsScope}/>)}
|
|
808
808
|
|
|
809
|
-
{renderGlass && !huge && (<Icon glyph={searchIcon} className={styles.icon} title={
|
|
809
|
+
{renderGlass && !huge && (<Icon glyph={searchIcon} className={styles.icon} title={translations?.searchTitle ?? translate('searchTitle')} ref={this.glassRef} data-test="query-assist-search-icon"/>)}
|
|
810
810
|
|
|
811
811
|
{renderLoader && (<div className={classNames(styles.icon, styles.loader, {
|
|
812
812
|
[styles.loaderOnTheRight]: !glass && !huge,
|
|
@@ -815,7 +815,7 @@ class QueryAssist extends Component {
|
|
|
815
815
|
<LoaderInline />
|
|
816
816
|
</div>)}
|
|
817
817
|
|
|
818
|
-
<ContentEditable aria-label={
|
|
818
|
+
<ContentEditable aria-label={translations?.searchTitle ?? translate('searchTitle')} className={inputClasses} data-test="ring-query-assist-input" inputRef={this.inputRef} disabled={this.props.disabled} onComponentUpdate={() => this.setCaretPosition({ fromContentEditable: true })} onBlur={this.handleFocusChange} onClick={this.handleCaretMove} onCompositionStart={this.trackCompositionState} onCompositionEnd={this.trackCompositionState} onFocus={this.handleFocusChange} onInput={this.handleInput} // To support IE use the same method
|
|
819
819
|
onKeyUp={this.handleInput} // to handle input and key up
|
|
820
820
|
onKeyDown={this.handleEnter} onPaste={this.handlePaste} spellCheck="false">{this.state.query && <span>{this.renderQuery()}</span>}</ContentEditable>
|
|
821
821
|
|
|
@@ -830,7 +830,7 @@ class QueryAssist extends Component {
|
|
|
830
830
|
<PopupMenu hidden={!this.state.showPopup} onCloseAttempt={this.closePopup} ref={this.popupRef} anchorElement={this.node} keepMounted attached className={this.props.popupClassName} directions={[PopupMenu.PopupProps.Directions.BOTTOM_RIGHT]} data={useCustomItemRender ? this.state.suggestions : this.renderSuggestions()} data-test="ring-query-assist-popup" hint={this.props.hint} hintOnSelection={this.props.hintOnSelection} left={this.getPopupOffset(this.state.suggestions)} maxHeight={PopupMenu.PopupProps.MaxHeight.SCREEN} onMouseDown={this.trackPopupMouseState} onMouseUp={this.trackPopupMouseState} onSelect={item => this.handleComplete(item)}/>
|
|
831
831
|
|
|
832
832
|
{glass && huge && (<div className={styles.rightSearchButton} data-test="query-assist-search-button">
|
|
833
|
-
<Icon glyph={searchIcon} className={styles.rightSearchIcon} title={
|
|
833
|
+
<Icon glyph={searchIcon} className={styles.rightSearchIcon} title={translations?.searchTitle ?? translate('searchTitle')} onClick={this.handleApply} ref={this.glassRef} data-test="query-assist-search-icon"/>
|
|
834
834
|
</div>)}
|
|
835
835
|
</div>)}
|
|
836
836
|
</I18nContext.Consumer>
|
|
@@ -423,13 +423,13 @@ class Select extends Component {
|
|
|
423
423
|
const { showPopup, shownData } = this.state;
|
|
424
424
|
const _shownData = this._prependResetOption(shownData);
|
|
425
425
|
return (<I18nContext.Consumer>
|
|
426
|
-
{
|
|
426
|
+
{({ translate }) => {
|
|
427
427
|
let message;
|
|
428
428
|
if (this.props.loading) {
|
|
429
|
-
message = this.props.loadingMessage ??
|
|
429
|
+
message = this.props.loadingMessage ?? translate('loading');
|
|
430
430
|
}
|
|
431
431
|
else if (!shownData.length) {
|
|
432
|
-
message = this.props.notFoundMessage ??
|
|
432
|
+
message = this.props.notFoundMessage ?? translate('noOptionsFound');
|
|
433
433
|
}
|
|
434
434
|
return (<SelectPopup data={_shownData} message={message} toolbar={showPopup && this.getToolbar()} loading={this.props.loading} activeIndex={this.state.selectedIndex} hidden={!showPopup} ref={this.popupRef} maxHeight={this.props.maxHeight} minWidth={this.props.minWidth} directions={this.props.directions} className={this.props.popupClassName} style={this.props.popupStyle} top={this.props.top} left={this.props.left} filter={this.isInputMode() ? false : this.props.filter} // disable popup filter in INPUT mode
|
|
435
435
|
multiple={this.props.multiple} filterValue={this.state.filterValue} anchorElement={anchorElement} onCloseAttempt={this._onCloseAttempt} onSelect={this._listSelectHandler} onSelectAll={this._listSelectAllHandler} onFilter={this._filterChangeHandler} onClear={this.clearFilter} onLoadMore={this.props.onLoadMore} isInputMode={this.isInputMode()} selected={this.state.selected} tags={this.props.tags} compact={this.props.compact} renderOptimization={this.props.renderOptimization} ringPopupTarget={this.props.ringPopupTarget} disableMoveOverflow={this.props.disableMoveOverflow} disableScrollToActive={this.props.disableScrollToActive} dir={this.props.dir} onEmptyPopupEnter={this.onEmptyPopupEnter} listId={this.listId}/>);
|
|
@@ -35,7 +35,7 @@ class SelectFilter extends Component {
|
|
|
35
35
|
const classes = classNames(styles.filter, className);
|
|
36
36
|
return (<ActiveItemContext.ValueContext.Consumer>
|
|
37
37
|
{activeItemId => (<I18nContext.Consumer>
|
|
38
|
-
{
|
|
38
|
+
{({ translate }) => (<Input {...restProps} placeholder={restProps.placeholder ?? translate('filterItems')} aria-owns={listId} aria-activedescendant={activeItemId} autoComplete="off" autoFocus borderless inputRef={this.inputRef} className={classes}/>)}
|
|
39
39
|
</I18nContext.Consumer>)}
|
|
40
40
|
</ActiveItemContext.ValueContext.Consumer>);
|
|
41
41
|
}
|
|
@@ -48,32 +48,32 @@ class UserAgreement extends PureComponent {
|
|
|
48
48
|
const { scrolledDown } = this.state;
|
|
49
49
|
const { translations, onAccept, onDecline, onClose, onRemindLater, text, show, preview, className } = this.props;
|
|
50
50
|
return (<I18nContext.Consumer>
|
|
51
|
-
{
|
|
52
|
-
<Header>{
|
|
51
|
+
{({ translate }) => (<Dialog label={translations?.userAgreement ?? translate('userAgreement')} show={show} className={classNames(style.agreementDialog, className)} contentClassName={style.dialogContent} trapFocus autoFocusFirst={false} data-test="user-agreement">
|
|
52
|
+
<Header>{translations?.userAgreement ?? translate('userAgreement')}</Header>
|
|
53
53
|
<Content fade onScrollToBottom={this.onScrollToBottom}>
|
|
54
54
|
<Markdown>{text}</Markdown>
|
|
55
55
|
</Content>
|
|
56
56
|
{!preview && (<Panel>
|
|
57
57
|
{onRemindLater && !scrolledDown && (<div className={style.suggestion}>
|
|
58
|
-
{
|
|
58
|
+
{translations?.scrollToAccept ?? translate('scrollToAccept')}
|
|
59
59
|
</div>)}
|
|
60
60
|
<Button primary disabled={!scrolledDown} onClick={onAccept} data-test="accept">
|
|
61
|
-
{
|
|
61
|
+
{translations?.accept ?? translate('accept')}
|
|
62
62
|
</Button>
|
|
63
63
|
<Button onClick={onDecline} autoFocus data-test="decline">
|
|
64
|
-
{
|
|
64
|
+
{translations?.decline ?? translate('decline')}
|
|
65
65
|
</Button>
|
|
66
66
|
|
|
67
67
|
{!onRemindLater && !scrolledDown && (<span className={style.suggestion}>
|
|
68
|
-
{
|
|
68
|
+
{translations?.scrollToAccept ?? translate('scrollToAccept')}
|
|
69
69
|
</span>)}
|
|
70
70
|
{onRemindLater && (<Button className={style.remindLaterButton} onClick={onRemindLater} data-test="later">
|
|
71
|
-
{
|
|
71
|
+
{translations?.remindLater ?? translate('remindLater')}
|
|
72
72
|
</Button>)}
|
|
73
73
|
</Panel>)}
|
|
74
74
|
{preview && (<Panel>
|
|
75
75
|
<Button onClick={onClose} autoFocus data-test="close">
|
|
76
|
-
{
|
|
76
|
+
{translations?.close ?? translate('close')}
|
|
77
77
|
</Button>
|
|
78
78
|
</Panel>)}
|
|
79
79
|
</Dialog>)}
|