diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e09980c20..3368762101 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@ Changelog
## vNext
+### Features
+
+- Implemented date, time and number format user options ([PR 1611](https://github.com/input-output-hk/daedalus/pull/1611))
+
### Chores
- Fixed build mode of webpack auto dll plugin ([PR 1606](https://github.com/input-output-hk/daedalus/pull/1606))
diff --git a/source/common/types/number.types.js b/source/common/types/number.types.js
new file mode 100644
index 0000000000..07b7dba79b
--- /dev/null
+++ b/source/common/types/number.types.js
@@ -0,0 +1,33 @@
+// @flow
+export type NumberFormat = {
+ groupSeparator: '.' | ',' | ' ',
+ decimalSeparator: '.' | ',' | ' ',
+};
+
+type NumbersFormat = {
+ [key: string]: NumberFormat,
+};
+
+export const NUMBER_FORMATS: NumbersFormat = {
+ 'number-1': {
+ groupSeparator: ',',
+ decimalSeparator: '.',
+ },
+ 'number-2': {
+ groupSeparator: '.',
+ decimalSeparator: ',',
+ },
+ 'number-3': {
+ groupSeparator: ' ',
+ decimalSeparator: '.',
+ },
+};
+
+export const DEFAULT_NUMBER_FORMAT: Object = {
+ decimalSeparator: '.',
+ groupSeparator: ',',
+ groupSize: 3,
+ secondaryGroupSize: 0,
+ fractionGroupSeparator: ' ',
+ fractionGroupSize: 0,
+};
diff --git a/source/renderer/app/Routes.js b/source/renderer/app/Routes.js
index 0880aed7d4..264da22442 100644
--- a/source/renderer/app/Routes.js
+++ b/source/renderer/app/Routes.js
@@ -5,7 +5,7 @@ import { ROUTES } from './routes-config';
// PAGES
import Root from './containers/Root';
-import LanguageSelectionPage from './containers/profile/LanguageSelectionPage';
+import InitialSettingsPage from './containers/profile/InitialSettingsPage';
import Settings from './containers/settings/Settings';
import GeneralSettingsPage from './containers/settings/categories/GeneralSettingsPage';
import SupportSettingsPage from './containers/settings/categories/SupportSettingsPage';
@@ -34,8 +34,8 @@ export const Routes = (
= new Action();
downloadLogsSuccess: Action = new Action();
- updateLocale: Action<{ locale: string }> = new Action();
+ updateUserLocalSetting: Action<{
+ param: string,
+ value?: string,
+ }> = new Action();
updateTheme: Action<{ theme: string }> = new Action();
+ finishInitialScreenSettings: Action = new Action();
}
diff --git a/source/renderer/app/api/transactions/types.js b/source/renderer/app/api/transactions/types.js
index 66517d23b6..8b62450f90 100644
--- a/source/renderer/app/api/transactions/types.js
+++ b/source/renderer/app/api/transactions/types.js
@@ -20,6 +20,7 @@ export type Transaction = {
tag: 'applying' | 'inNewestBlocks' | 'persisted' | 'wontApply' | 'creating',
data: {},
},
+ currentTimeFormat: string,
};
export type PaymentDistribution = {
diff --git a/source/renderer/app/api/utils/localStorage.js b/source/renderer/app/api/utils/localStorage.js
index 107122df1c..316d45f697 100644
--- a/source/renderer/app/api/utils/localStorage.js
+++ b/source/renderer/app/api/utils/localStorage.js
@@ -18,12 +18,7 @@ export type WalletsLocalData = {
};
type StorageKeys = {
- USER_LOCALE: string,
- TERMS_OF_USE_ACCEPTANCE: string,
- THEME: string,
- DATA_LAYER_MIGRATION_ACCEPTANCE: string,
- READ_NEWS: string,
- WALLETS: string,
+ [key: string]: string,
};
/**
@@ -32,173 +27,159 @@ type StorageKeys = {
*/
export default class LocalStorageApi {
- storageKeys: StorageKeys;
-
- constructor(NETWORK: string) {
- this.storageKeys = {
- USER_LOCALE: `${NETWORK}-USER-LOCALE`,
- TERMS_OF_USE_ACCEPTANCE: `${NETWORK}-TERMS-OF-USE-ACCEPTANCE`,
- THEME: `${NETWORK}-THEME`,
- DATA_LAYER_MIGRATION_ACCEPTANCE: `${NETWORK}-DATA-LAYER-MIGRATION-ACCEPTANCE`,
- READ_NEWS: `${NETWORK}-READ_NEWS`,
- WALLETS: `${NETWORK}-WALLETS`,
- };
- }
-
- getUserLocale = (): Promise =>
+ static Getter = (key: string, fallbackValue: any): Promise =>
new Promise((resolve, reject) => {
try {
- const locale = store.get(this.storageKeys.USER_LOCALE);
- if (!locale) return resolve('');
- resolve(locale);
+ const value = store.get(key);
+ if (!value) return resolve(fallbackValue);
+ resolve(value);
} catch (error) {
return reject(error);
}
});
- setUserLocale = (locale: string): Promise =>
+ static Setter = (key: string, value: any): Promise =>
new Promise((resolve, reject) => {
try {
- store.set(this.storageKeys.USER_LOCALE, locale);
+ store.set(key, value);
resolve();
} catch (error) {
return reject(error);
}
});
- unsetUserLocale = (): Promise =>
+ static Unsetter = (key: string): Promise =>
new Promise(resolve => {
try {
- store.delete(this.storageKeys.USER_LOCALE);
+ store.delete(key);
resolve();
} catch (error) {} // eslint-disable-line
});
- getTermsOfUseAcceptance = (): Promise =>
- new Promise((resolve, reject) => {
- try {
- const accepted = store.get(this.storageKeys.TERMS_OF_USE_ACCEPTANCE);
- if (!accepted) return resolve(false);
- resolve(accepted);
- } catch (error) {
- return reject(error);
- }
+ storageKeys: StorageKeys;
+
+ constructor(NETWORK: string) {
+ const storageKeysRaw = [
+ 'USER_LOCALE',
+ 'USER_NUMBER_FORMAT',
+ 'USER_DATE_FORMAT_ENGLISH',
+ 'USER_DATE_FORMAT_JAPANESE',
+ 'USER_TIME_FORMAT',
+ 'TERMS_OF_USE_ACCEPTANCE',
+ 'THEME',
+ 'DATA_LAYER_MIGRATION_ACCEPTANCE',
+ 'READ_NEWS',
+ 'WALLETS',
+ ];
+ this.storageKeys = {};
+ storageKeysRaw.forEach(key => {
+ const keyStr = key.replace(new RegExp('_', 'g'), '-');
+ this.storageKeys[key] = `${NETWORK}-${keyStr}`;
});
+ }
+
+ getUserLocale = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.USER_LOCALE, '');
+
+ setUserLocale = (locale: string): Promise =>
+ new LocalStorageApi.Setter(this.storageKeys.USER_LOCALE, locale);
+
+ unsetUserLocale = (): Promise =>
+ new LocalStorageApi.Unsetter(this.storageKeys.USER_LOCALE);
+
+ getUserNumberFormat = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.USER_NUMBER_FORMAT, '');
+
+ setUserNumberFormat = (numberFormat: string): Promise =>
+ new LocalStorageApi.Setter(
+ this.storageKeys.USER_NUMBER_FORMAT,
+ numberFormat
+ );
+
+ unsetUserNumberFormat = (): Promise =>
+ new LocalStorageApi.Unsetter(this.storageKeys.USER_NUMBER_FORMAT);
+
+ getUserDateFormatEnglish = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.USER_DATE_FORMAT_ENGLISH, '');
+
+ setUserDateFormatEnglish = (dateFormat: string): Promise =>
+ new LocalStorageApi.Setter(
+ this.storageKeys.USER_DATE_FORMAT_ENGLISH,
+ dateFormat
+ );
+
+ unsetUserDateFormatEnglish = (): Promise =>
+ new LocalStorageApi.Unsetter(this.storageKeys.USER_DATE_FORMAT_ENGLISH);
+
+ getUserDateFormatJapanese = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.USER_DATE_FORMAT_JAPANESE, '');
+
+ setUserDateFormatJapanese = (dateFormat: string): Promise =>
+ new LocalStorageApi.Setter(
+ this.storageKeys.USER_DATE_FORMAT_JAPANESE,
+ dateFormat
+ );
+
+ unsetUserDateFormatJapanese = (): Promise =>
+ new LocalStorageApi.Unsetter(this.storageKeys.USER_DATE_FORMAT_JAPANESE);
+
+ getUserTimeFormat = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.USER_TIME_FORMAT, '');
+
+ setUserTimeFormat = (timeFormat: string): Promise =>
+ new LocalStorageApi.Setter(this.storageKeys.USER_TIME_FORMAT, timeFormat);
+
+ unsetUserTimeFormat = (): Promise =>
+ new LocalStorageApi.Unsetter(this.storageKeys.USER_TIME_FORMAT);
+
+ getTermsOfUseAcceptance = (): Promise =>
+ new LocalStorageApi.Getter(this.storageKeys.TERMS_OF_USE_ACCEPTANCE, false);
setTermsOfUseAcceptance = (): Promise =>
- new Promise((resolve, reject) => {
- try {
- store.set(this.storageKeys.TERMS_OF_USE_ACCEPTANCE, true);
- resolve();
- } catch (error) {
- return reject(error);
- }
- });
+ new LocalStorageApi.Setter(this.storageKeys.TERMS_OF_USE_ACCEPTANCE, true);
unsetTermsOfUseAcceptance = (): Promise =>
- new Promise(resolve => {
- try {
- store.delete(this.storageKeys.TERMS_OF_USE_ACCEPTANCE);
- resolve();
- } catch (error) {} // eslint-disable-line
- });
+ new LocalStorageApi.Unsetter(this.storageKeys.TERMS_OF_USE_ACCEPTANCE);
getUserTheme = (): Promise =>
- new Promise((resolve, reject) => {
- try {
- const theme = store.get(this.storageKeys.THEME);
- if (!theme) return resolve('');
- resolve(theme);
- } catch (error) {
- return reject(error);
- }
- });
+ new LocalStorageApi.Getter(this.storageKeys.THEME, '');
setUserTheme = (theme: string): Promise =>
- new Promise((resolve, reject) => {
- try {
- store.set(this.storageKeys.THEME, theme);
- resolve();
- } catch (error) {
- return reject(error);
- }
- });
+ new LocalStorageApi.Setter(this.storageKeys.THEME, theme);
unsetUserTheme = (): Promise =>
- new Promise(resolve => {
- try {
- store.delete(this.storageKeys.THEME);
- resolve();
- } catch (error) {} // eslint-disable-line
- });
+ new LocalStorageApi.Unsetter(this.storageKeys.THEME);
getDataLayerMigrationAcceptance = (): Promise =>
- new Promise((resolve, reject) => {
- try {
- const accepted = store.get(
- this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE
- );
- if (!accepted) return resolve(false);
- resolve(true);
- } catch (error) {
- return reject(error);
- }
- });
+ new LocalStorageApi.Getter(
+ this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE,
+ false
+ );
setDataLayerMigrationAcceptance = (): Promise =>
- new Promise((resolve, reject) => {
- try {
- store.set(this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE, true);
- resolve();
- } catch (error) {
- return reject(error);
- }
- });
+ new LocalStorageApi.Setter(
+ this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE,
+ true
+ );
unsetDataLayerMigrationAcceptance = (): Promise =>
- new Promise(resolve => {
- try {
- store.delete(this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE);
- resolve();
- } catch (error) {} // eslint-disable-line
- });
+ new LocalStorageApi.Unsetter(
+ this.storageKeys.DATA_LAYER_MIGRATION_ACCEPTANCE
+ );
getWalletsLocalData = (): Promise
- 15.042481 ADA
+ {formattedWalletAmount(amount.add(fees), false)}
+ ADA
diff --git a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js
index 684b56a739..33a4a1b32b 100644
--- a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js
+++ b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js
@@ -7,6 +7,7 @@ import { Stepper } from 'react-polymorph/lib/components/Stepper';
import { StepperSkin } from 'react-polymorph/lib/skins/simple/StepperSkin';
import { Input } from 'react-polymorph/lib/components/Input';
import { InputSkin } from 'react-polymorph/lib/skins/simple/InputSkin';
+import BigNumber from 'bignumber.js';
import commonStyles from './DelegationSteps.scss';
import styles from './DelegationStepsConfirmationDialog.scss';
import DialogCloseButton from '../../widgets/DialogCloseButton';
@@ -16,6 +17,7 @@ import ReactToolboxMobxForm from '../../../utils/ReactToolboxMobxForm';
import { submitOnEnter } from '../../../utils/form';
import globalMessages from '../../../i18n/global-messages';
import { FORM_VALIDATION_DEBOUNCE_WAIT } from '../../../config/timingConfig';
+import { formattedWalletAmount } from '../../../utils/formatters';
const messages = defineMessages({
title: {
@@ -76,6 +78,7 @@ type Props = {
onBack: Function,
onClose: Function,
onConfirm: Function,
+ fees: BigNumber,
stepsList: Array,
};
@@ -142,7 +145,13 @@ export default class DelegationStepsConfirmationDialog extends Component
render() {
const { form } = this;
const { intl } = this.context;
- const { isSpendingPasswordSet, onBack, onClose, stepsList } = this.props;
+ const {
+ isSpendingPasswordSet,
+ onBack,
+ onClose,
+ stepsList,
+ fees,
+ } = this.props;
const spendingPasswordField = form.$('spendingPassword');
@@ -206,7 +215,8 @@ export default class DelegationStepsConfirmationDialog extends Component
{intl.formatMessage(messages.feesLabel)}
- 0.172081 ADA
+ {formattedWalletAmount(fees, false)}
+ ADA
diff --git a/source/renderer/app/components/staking/rewards/StakingRewards.js b/source/renderer/app/components/staking/rewards/StakingRewards.js
index 4b0594de72..209765ee88 100644
--- a/source/renderer/app/components/staking/rewards/StakingRewards.js
+++ b/source/renderer/app/components/staking/rewards/StakingRewards.js
@@ -5,12 +5,14 @@ import { defineMessages, intlShape } from 'react-intl';
import SVGInline from 'react-svg-inline';
import { get, map, orderBy } from 'lodash';
import classNames from 'classnames';
+import { BigNumber } from 'bignumber.js';
import BorderedBox from '../../widgets/BorderedBox';
import LoadingSpinner from '../../widgets/LoadingSpinner';
import sortIcon from '../../../assets/images/ascending.inline.svg';
import externalLinkIcon from '../../../assets/images/link-ic.inline.svg';
import type { Reward } from '../../../api/staking/types';
import styles from './StakingRewards.scss';
+import { SIMPLE_DECIMAL_PLACES_IN_ADA } from '../../../config/numbersConfig';
const messages = defineMessages({
title: {
@@ -192,7 +194,12 @@ export default class StakingRewards extends Component {
{rewardWallet} |
- {rewardAmount} ADA |
+
+ {new BigNumber(rewardAmount).toFormat(
+ SIMPLE_DECIMAL_PLACES_IN_ADA
+ )}{' '}
+ ADA
+ |
);
})}
diff --git a/source/renderer/app/components/status/DaedalusDiagnostics.js b/source/renderer/app/components/status/DaedalusDiagnostics.js
index 44f0578e4d..5f28c3f8bc 100644
--- a/source/renderer/app/components/status/DaedalusDiagnostics.js
+++ b/source/renderer/app/components/status/DaedalusDiagnostics.js
@@ -9,6 +9,7 @@ import CopyToClipboard from 'react-copy-to-clipboard';
import { Tooltip } from 'react-polymorph/lib/components/Tooltip';
import { TooltipSkin } from 'react-polymorph/lib/skins/simple/TooltipSkin';
import SVGInline from 'react-svg-inline';
+import { BigNumber } from 'bignumber.js';
import {
ALLOWED_TIME_DIFFERENCE,
MAX_ALLOWED_STALL_DURATION,
@@ -759,15 +760,24 @@ export default class DaedalusDiagnostics extends Component {
{intl.formatMessage(messages.syncPercentage)}: |
- {syncPercentage.toFixed(2)}% |
+
+ {new BigNumber(
+ parseFloat(syncPercentage).toFixed(2)
+ ).toFormat(2)}
+ %
+ |
{intl.formatMessage(messages.networkBlockHeight)}: |
- {networkBlockHeight} |
+
+ {new BigNumber(parseInt(networkBlockHeight, 10)).toFormat(0)}
+ |
{intl.formatMessage(messages.localBlockHeight)}: |
- {localBlockHeight} |
+
+ {new BigNumber(parseInt(localBlockHeight, 10)).toFormat(0)}
+ |
{intl.formatMessage(messages.remainingUnsyncedBlocks)}: |
@@ -779,7 +789,9 @@ export default class DaedalusDiagnostics extends Component {
{intl.formatMessage(messages.latestLocalBlockAge)}: |
{latestLocalBlockTimestamp > 0
- ? `${latestLocalBlockAge} ms`
+ ? `${new BigNumber(
+ parseInt(latestLocalBlockAge, 10)
+ ).toFormat(0)} ms`
: '-'}
|
@@ -787,7 +799,9 @@ export default class DaedalusDiagnostics extends Component {
{intl.formatMessage(messages.latestNetworkBlockAge)}: |
{latestNetworkBlockTimestamp > 0
- ? `${latestNetworkBlockAge} ms`
+ ? `${new BigNumber(
+ parseInt(latestNetworkBlockAge, 10)
+ ).toFormat(0)} ms`
: '-'}
|
@@ -806,7 +820,9 @@ export default class DaedalusDiagnostics extends Component {
{isNTPServiceReachable
- ? `${localTimeDifference || 0} μs`
+ ? `${new BigNumber(
+ parseInt(localTimeDifference, 10)
+ ).toFormat(0) || 0} μs`
: intl.formatMessage(messages.serviceUnreachable)}
diff --git a/source/renderer/app/components/wallet/transactions/Transaction.js b/source/renderer/app/components/wallet/transactions/Transaction.js
index c33966949a..f70ea17690 100644
--- a/source/renderer/app/components/wallet/transactions/Transaction.js
+++ b/source/renderer/app/components/wallet/transactions/Transaction.js
@@ -138,6 +138,7 @@ type Props = {
network: string,
onDetailsToggled: ?Function,
onOpenExternalLink: ?Function,
+ currentTimeFormat: string,
};
export default class Transaction extends Component {
@@ -169,6 +170,7 @@ export default class Transaction extends Component {
onOpenExternalLink,
isRestoreActive,
isExpanded,
+ currentTimeFormat,
} = this.props;
const { intl } = this.context;
@@ -261,7 +263,7 @@ export default class Transaction extends Component {
{intl.formatMessage(messages.type, { currency })},{' '}
- {moment(data.date).format('hh:mm:ss A')}
+ {moment(data.date).format(currentTimeFormat)}
{transactionStateTag()}
diff --git a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js
index 07193d4905..1f379080dd 100644
--- a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js
+++ b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js
@@ -57,6 +57,8 @@ type Props = {
showMoreTransactionsButton?: boolean,
transactions: Array,
walletId: string,
+ currentTimeFormat: string,
+ currentDateFormat: string,
};
const DATE_FORMAT = 'YYYY-MM-DD';
@@ -79,14 +81,6 @@ export default class WalletTransactionsList extends Component {
virtualList: ?VirtualTransactionList;
simpleList: ?SimpleTransactionList;
loadingSpinner: ?LoadingSpinner;
- localizedDateFormat: 'MM/DD/YYYY';
-
- componentWillMount() {
- this.localizedDateFormat = moment.localeData().longDateFormat('L');
- // Localized dateFormat:
- // English - MM/DD/YYYY
- // Japanese - YYYY/MM/DD
- }
groupTransactionsByDay(
transactions: Array
@@ -123,6 +117,7 @@ export default class WalletTransactionsList extends Component {
localizedDate(date: string) {
const { intl } = this.context;
+ const { currentDateFormat } = this.props;
// TODAY
const today = moment().format(DATE_FORMAT);
if (date === today) return intl.formatMessage(messages.today);
@@ -132,7 +127,7 @@ export default class WalletTransactionsList extends Component {
.format(DATE_FORMAT);
if (date === yesterday) return intl.formatMessage(messages.yesterday);
// PAST DATE
- return moment(date).format(this.localizedDateFormat);
+ return moment(date).format(currentDateFormat);
}
isTxExpanded = (tx: WalletTransaction) =>
@@ -185,6 +180,7 @@ export default class WalletTransactionsList extends Component {
isRestoreActive,
network,
onOpenExternalLink,
+ currentTimeFormat,
} = this.props;
const { isFirstInGroup, isLastInGroup, tx } = data;
const txClasses = classnames([
@@ -205,6 +201,7 @@ export default class WalletTransactionsList extends Component {
onDetailsToggled={() => this.toggleTransactionExpandedState(tx)}
onOpenExternalLink={onOpenExternalLink}
state={tx.state}
+ currentTimeFormat={currentTimeFormat}
/>
);
diff --git a/source/renderer/app/components/widgets/forms/ProfileSettingsForm.js b/source/renderer/app/components/widgets/forms/ProfileSettingsForm.js
new file mode 100644
index 0000000000..9e7ced4134
--- /dev/null
+++ b/source/renderer/app/components/widgets/forms/ProfileSettingsForm.js
@@ -0,0 +1,142 @@
+// @flow
+import React, { Component } from 'react';
+import { observer } from 'mobx-react';
+import classNames from 'classnames';
+import { Button } from 'react-polymorph/lib/components/Button';
+import { Select } from 'react-polymorph/lib/components/Select';
+import { ButtonSpinnerSkin } from 'react-polymorph/lib/skins/simple/ButtonSpinnerSkin';
+import { SelectSkin } from 'react-polymorph/lib/skins/simple/SelectSkin';
+import { defineMessages, intlShape } from 'react-intl';
+import LocalizableError from '../../../i18n/LocalizableError';
+import styles from './ProfileSettingsForm.scss';
+import {
+ LANGUAGE_OPTIONS,
+ NUMBER_OPTIONS,
+ DATE_ENGLISH_OPTIONS,
+ DATE_JAPANESE_OPTIONS,
+ TIME_OPTIONS,
+ PROFILE_SETTINGS,
+} from '../../../config/profileConfig';
+
+const messages = defineMessages({
+ localeSelectLabel: {
+ id: 'profile.settings.languageSelect.label',
+ defaultMessage: '!!!Language',
+ description: 'Label for the language select.',
+ },
+ numberFormatSelectLabel: {
+ id: 'profile.settings.numberSelect.label',
+ defaultMessage: '!!!Number format',
+ description: 'Label for the number select.',
+ },
+ dateFormatSelectLabel: {
+ id: 'profile.settings.dateSelect.label',
+ defaultMessage: '!!!Date format',
+ description: 'Label for the date select.',
+ },
+ timeFormatSelectLabel: {
+ id: 'profile.settings.timeSelect.label',
+ defaultMessage: '!!!Time format',
+ description: 'Label for the time select.',
+ },
+ submitLabel: {
+ id: 'profile.settings.submitLabel',
+ defaultMessage: '!!!Continue',
+ description: 'Label for the "Language select" form submit button.',
+ },
+});
+
+export type ProfileSettingsFormProps = {
+ currentLocale: string,
+ currentNumberFormat: string,
+ currentDateFormat: string,
+ currentTimeFormat: string,
+ onChangeItem: Function,
+ onSubmit?: Function,
+ isSubmitting?: boolean,
+ error?: ?LocalizableError,
+};
+
+@observer
+export default class ProfileSettingsForm extends Component {
+ static defaultProps = {
+ onChangeItem: () => {},
+ };
+
+ static contextTypes = {
+ intl: intlShape.isRequired,
+ };
+
+ get locale() {
+ const { props, context } = this;
+ const options = LANGUAGE_OPTIONS.map(language => ({
+ value: language.value,
+ label: context.intl.formatMessage(language.label),
+ }));
+ const value = props.currentLocale;
+ return { value, options };
+ }
+
+ get numberFormat() {
+ return {
+ options: NUMBER_OPTIONS,
+ value: this.props.currentNumberFormat,
+ };
+ }
+
+ get dateFormat() {
+ const { currentLocale, currentDateFormat } = this.props;
+ return {
+ options:
+ currentLocale === 'en-US'
+ ? DATE_ENGLISH_OPTIONS
+ : DATE_JAPANESE_OPTIONS,
+ value: currentDateFormat,
+ };
+ }
+
+ get timeFormat() {
+ return {
+ options: TIME_OPTIONS,
+ value: this.props.currentTimeFormat,
+ };
+ }
+
+ getSelect = (id: string) => {
+ const { formatMessage } = this.context.intl;
+ const { onChangeItem } = this.props;
+ const { value, options } = (this: any)[id];
+ return (
+