From b579ee9619d5d775484f382b800c3426311da19d Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 11 Sep 2018 17:32:37 -0700 Subject: Refactor settings page to use JSX and follow component file folder structure --- app/_locales/en/messages.json | 9 + test/e2e/beta/metamask-beta-ui.spec.js | 2 +- ui/app/app.js | 2 +- ui/app/components/pages/index.scss | 2 + ui/app/components/pages/settings/index.js | 65 +--- ui/app/components/pages/settings/index.scss | 80 ++++ ui/app/components/pages/settings/info-tab/index.js | 1 + .../components/pages/settings/info-tab/index.scss | 60 +++ .../pages/settings/info-tab/info-tab.component.js | 136 +++++++ ui/app/components/pages/settings/info.js | 120 ------ .../pages/settings/settings-tab/index.js | 1 + .../pages/settings/settings-tab/index.scss | 51 +++ .../settings-tab/settings-tab.component.js | 359 ++++++++++++++++++ .../settings-tab/settings-tab.container.js | 59 +++ .../pages/settings/settings.component.js | 54 +++ ui/app/components/pages/settings/settings.js | 408 --------------------- ui/app/css/itcss/components/index.scss | 2 - ui/app/css/itcss/components/settings.scss | 214 ----------- 18 files changed, 815 insertions(+), 810 deletions(-) create mode 100644 ui/app/components/pages/settings/index.scss create mode 100644 ui/app/components/pages/settings/info-tab/index.js create mode 100644 ui/app/components/pages/settings/info-tab/index.scss create mode 100644 ui/app/components/pages/settings/info-tab/info-tab.component.js delete mode 100644 ui/app/components/pages/settings/info.js create mode 100644 ui/app/components/pages/settings/settings-tab/index.js create mode 100644 ui/app/components/pages/settings/settings-tab/index.scss create mode 100644 ui/app/components/pages/settings/settings-tab/settings-tab.component.js create mode 100644 ui/app/components/pages/settings/settings-tab/settings-tab.container.js create mode 100644 ui/app/components/pages/settings/settings.component.js delete mode 100644 ui/app/components/pages/settings/settings.js delete mode 100644 ui/app/css/itcss/components/settings.scss diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 2cfd15f50..359eee9ef 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -216,6 +216,9 @@ "currentConversion": { "message": "Current Conversion" }, + "currentLanguage": { + "message": "current language" + }, "currentNetwork": { "message": "Current Network" }, @@ -596,6 +599,9 @@ "metamaskSeedWords": { "message": "MetaMask Seed Words" }, + "metamaskVersion": { + "message": "metamask version" + }, "min": { "message": "Minimum" }, @@ -906,6 +912,9 @@ "selectCurrency": { "message": "Select Currency" }, + "selectLocale": { + "message": "Select Locale" + }, "selectService": { "message": "Select Service" }, diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 0864ef236..7370f1a92 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -1043,7 +1043,7 @@ describe('MetaMask', function () { await customRpcInput.clear() await customRpcInput.sendKeys(customRpcUrl) - const customRpcSave = await findElement(driver, By.css('.settings__rpc-save-button')) + const customRpcSave = await findElement(driver, By.css('.settings-tab__rpc-save-button')) await customRpcSave.click() await delay(largeDelayMs * 2) }) diff --git a/ui/app/app.js b/ui/app/app.js index c93f93e75..f1590d89e 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -19,9 +19,9 @@ const Sidebar = require('./components/sidebars').default // other views import Home from './components/pages/home' +import Settings from './components/pages/settings' const Authenticated = require('./components/pages/authenticated') const Initialized = require('./components/pages/initialized') -const Settings = require('./components/pages/settings') const RestoreVaultPage = require('./components/pages/keychains/restore-vault').default const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed') const AddTokenPage = require('./components/pages/add-token') diff --git a/ui/app/components/pages/index.scss b/ui/app/components/pages/index.scss index b15c59863..6551278f5 100644 --- a/ui/app/components/pages/index.scss +++ b/ui/app/components/pages/index.scss @@ -3,3 +3,5 @@ @import './add-token/index'; @import './confirm-add-token/index'; + +@import './settings/index'; diff --git a/ui/app/components/pages/settings/index.js b/ui/app/components/pages/settings/index.js index aee17e0e8..44a9ffa63 100644 --- a/ui/app/components/pages/settings/index.js +++ b/ui/app/components/pages/settings/index.js @@ -1,64 +1 @@ -const { Component } = require('react') -const { Switch, Route, matchPath } = require('react-router-dom') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const TabBar = require('../../tab-bar') -const Settings = require('./settings') -const Info = require('./info') -const { DEFAULT_ROUTE, SETTINGS_ROUTE, INFO_ROUTE } = require('../../../routes') - -class Config extends Component { - renderTabs () { - const { history, location } = this.props - - return h('div.settings__tabs', [ - h(TabBar, { - tabs: [ - { content: this.context.t('settings'), key: SETTINGS_ROUTE }, - { content: this.context.t('info'), key: INFO_ROUTE }, - ], - isActive: key => matchPath(location.pathname, { path: key, exact: true }), - onSelect: key => history.push(key), - }), - ]) - } - - render () { - const { history } = this.props - - return ( - h('.main-container.settings', {}, [ - h('.settings__header', [ - h('div.settings__close-button', { - onClick: () => history.push(DEFAULT_ROUTE), - }), - this.renderTabs(), - ]), - h(Switch, [ - h(Route, { - exact: true, - path: INFO_ROUTE, - component: Info, - }), - h(Route, { - exact: true, - path: SETTINGS_ROUTE, - component: Settings, - }), - ]), - ]) - ) - } -} - -Config.propTypes = { - location: PropTypes.object, - history: PropTypes.object, - t: PropTypes.func, -} - -Config.contextTypes = { - t: PropTypes.func, -} - -module.exports = Config +export { default } from './settings.component' diff --git a/ui/app/components/pages/settings/index.scss b/ui/app/components/pages/settings/index.scss new file mode 100644 index 000000000..138ebcfc5 --- /dev/null +++ b/ui/app/components/pages/settings/index.scss @@ -0,0 +1,80 @@ +@import './info-tab/index'; + +@import './settings-tab/index'; + +.settings-page { + position: relative; + background: $white; + display: flex; + flex-flow: column nowrap; + + &__header { + padding: 25px 25px 0; + } + + &__close-button::after { + content: '\00D7'; + font-size: 40px; + color: $dusty-gray; + position: absolute; + top: 25px; + right: 30px; + cursor: pointer; + } + + &__content { + padding: 25px; + height: auto; + overflow: auto; + } + + &__content-row { + display: flex; + flex-direction: row; + padding: 10px 0 20px; + + @media screen and (max-width: 575px) { + flex-direction: column; + padding: 10px 0; + } + } + + &__content-item { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + padding: 0 5px; + min-height: 71px; + + @media screen and (max-width: 575px) { + height: initial; + padding: 5px 0; + } + + &--without-height { + height: initial; + } + } + + &__content-label { + text-transform: capitalize; + } + + &__content-description { + font-size: 14px; + color: $dusty-gray; + padding-top: 5px; + } + + &__content-item-col { + max-width: 300px; + display: flex; + flex-direction: column; + + @media screen and (max-width: 575px) { + max-width: 100%; + width: 100%; + } + } +} diff --git a/ui/app/components/pages/settings/info-tab/index.js b/ui/app/components/pages/settings/info-tab/index.js new file mode 100644 index 000000000..7556a258d --- /dev/null +++ b/ui/app/components/pages/settings/info-tab/index.js @@ -0,0 +1 @@ +export { default } from './info-tab.component' diff --git a/ui/app/components/pages/settings/info-tab/index.scss b/ui/app/components/pages/settings/info-tab/index.scss new file mode 100644 index 000000000..00342dc5f --- /dev/null +++ b/ui/app/components/pages/settings/info-tab/index.scss @@ -0,0 +1,60 @@ +.info-tab { + &__logo-wrapper { + height: 80px; + margin-bottom: 20px; + } + + &__logo { + max-height: 100%; + max-width: 100%; + } + + &__item { + padding: 10px 0; + } + + &__link-header { + padding-bottom: 15px; + + @media screen and (max-width: 575px) { + padding-bottom: 5px; + } + } + + &__link-item { + padding: 15px 0; + + @media screen and (max-width: 575px) { + padding: 5px 0; + } + } + + &__link-text { + color: $curious-blue; + } + + &__version-header { + text-transform: capitalize; + } + + &__version-number { + padding-top: 5px; + font-size: 13px; + color: $dusty-gray; + } + + &__separator { + margin: 15px 0; + width: 80px; + border-color: $alto; + border: none; + height: 1px; + background-color: $alto; + color: $alto; + } + + &__about { + color: $dusty-gray; + margin-bottom: 15px; + } +} diff --git a/ui/app/components/pages/settings/info-tab/info-tab.component.js b/ui/app/components/pages/settings/info-tab/info-tab.component.js new file mode 100644 index 000000000..72f7d835e --- /dev/null +++ b/ui/app/components/pages/settings/info-tab/info-tab.component.js @@ -0,0 +1,136 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' + +export default class InfoTab extends PureComponent { + state = { + version: global.platform.getVersion(), + } + + static propTypes = { + tab: PropTypes.string, + metamask: PropTypes.object, + setCurrentCurrency: PropTypes.func, + setRpcTarget: PropTypes.func, + displayWarning: PropTypes.func, + revealSeedConfirmation: PropTypes.func, + warning: PropTypes.string, + location: PropTypes.object, + history: PropTypes.object, + } + + static contextTypes = { + t: PropTypes.func, + } + + renderInfoLinks () { + const { t } = this.context + + return ( +
+
+ { t('links') } +
+
+ + + { t('privacyMsg') } + + +
+
+ + + { t('terms') } + + +
+
+ + + { t('attributions') } + + +
+
+
+ + + { t('supportCenter') } + + +
+
+ + + { t('visitWebSite') } + + +
+
+ + + { t('emailUs') } + + +
+
+ ) + } + + render () { + const { t } = this.context + + return ( +
+
+
+
+ +
+
+
+ { t('metamaskVersion') } +
+
+ { this.state.version } +
+
+
+
+ { t('builtInCalifornia') } +
+
+
+ { this.renderInfoLinks() } +
+
+ ) + } +} diff --git a/ui/app/components/pages/settings/info.js b/ui/app/components/pages/settings/info.js deleted file mode 100644 index bd9040499..000000000 --- a/ui/app/components/pages/settings/info.js +++ /dev/null @@ -1,120 +0,0 @@ -const { Component } = require('react') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') - -class Info extends Component { - constructor (props) { - super(props) - - this.state = { - version: global.platform.getVersion(), - } - } - - renderLogo () { - return ( - h('div.settings__info-logo-wrapper', [ - h('img.settings__info-logo', { src: 'images/info-logo.png' }), - ]) - ) - } - - renderInfoLinks () { - return ( - h('div.settings__content-item.settings__content-item--without-height', [ - h('div.settings__info-link-header', this.context.t('links')), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/privacy.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('privacyMsg')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/terms.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('terms')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/attributions.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('attributions')), - ]), - ]), - h('hr.settings__info-separator'), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://support.metamask.io', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('supportCenter')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('visitWebSite')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - target: '_blank', - href: 'mailto:help@metamask.io?subject=Feedback', - }, [ - h('span.settings__info-link', this.context.t('emailUs')), - ]), - ]), - ]) - ) - } - - render () { - return ( - h('div.settings__content', [ - h('div.settings__content-row', [ - h('div.settings__content-item.settings__content-item--without-height', [ - this.renderLogo(), - h('div.settings__info-item', [ - h('div.settings__info-version-header', 'MetaMask Version'), - h('div.settings__info-version-number', this.state.version), - ]), - h('div.settings__info-item', [ - h( - 'div.settings__info-about', - this.context.t('builtInCalifornia') - ), - ]), - ]), - this.renderInfoLinks(), - ]), - ]) - ) - } -} - -Info.propTypes = { - tab: PropTypes.string, - metamask: PropTypes.object, - setCurrentCurrency: PropTypes.func, - setRpcTarget: PropTypes.func, - displayWarning: PropTypes.func, - revealSeedConfirmation: PropTypes.func, - warning: PropTypes.string, - location: PropTypes.object, - history: PropTypes.object, - t: PropTypes.func, -} - -Info.contextTypes = { - t: PropTypes.func, -} - -module.exports = Info diff --git a/ui/app/components/pages/settings/settings-tab/index.js b/ui/app/components/pages/settings/settings-tab/index.js new file mode 100644 index 000000000..9fdaafd3f --- /dev/null +++ b/ui/app/components/pages/settings/settings-tab/index.js @@ -0,0 +1 @@ +export { default } from './settings-tab.container' diff --git a/ui/app/components/pages/settings/settings-tab/index.scss b/ui/app/components/pages/settings/settings-tab/index.scss new file mode 100644 index 000000000..76a0cec6f --- /dev/null +++ b/ui/app/components/pages/settings/settings-tab/index.scss @@ -0,0 +1,51 @@ +.settings-tab { + &__error { + padding-bottom: 20px; + text-align: center; + color: $crimson; + } + + &__rpc-save-button { + align-self: flex-end; + padding: 5px; + text-transform: uppercase; + color: $dusty-gray; + cursor: pointer; + } + + &__rpc-save-button { + align-self: flex-end; + padding: 5px; + text-transform: uppercase; + color: $dusty-gray; + cursor: pointer; + } + + &__button--red { + border-color: lighten($monzo, 10%); + color: $monzo; + + &:active { + background: lighten($monzo, 55%); + border-color: $monzo; + } + + &:hover { + border-color: $monzo; + } + } + + &__button--orange { + border-color: lighten($ecstasy, 20%); + color: $ecstasy; + + &:active { + background: lighten($ecstasy, 40%); + border-color: $ecstasy; + } + + &:hover { + border-color: $ecstasy; + } + } +} diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js new file mode 100644 index 000000000..543bd0bcc --- /dev/null +++ b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js @@ -0,0 +1,359 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import infuraCurrencies from '../../../../infura-conversion.json' +import validUrl from 'valid-url' +import { exportAsFile } from '../../../../util' +import SimpleDropdown from '../../../dropdowns/simple-dropdown' +import ToggleButton from 'react-toggle-button' +import { REVEAL_SEED_ROUTE } from '../../../../routes' +import locales from '../../../../../../app/_locales/index.json' +import TextField from '../../../text-field' +import Button from '../../../button' + +const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { + return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase()) +}) + +const infuraCurrencyOptions = sortedCurrencies.map(({ quote: { code, name } }) => { + return { + displayValue: `${code.toUpperCase()} - ${name}`, + key: code, + value: code, + } +}) + +const localeOptions = locales.map(locale => { + return { + displayValue: `${locale.name}`, + key: locale.code, + value: locale.code, + } +}) + +export default class SettingsTab extends PureComponent { + static contextTypes = { + t: PropTypes.func, + } + + static propTypes = { + metamask: PropTypes.object, + setUseBlockie: PropTypes.func, + setHexDataFeatureFlag: PropTypes.func, + setCurrentCurrency: PropTypes.func, + setRpcTarget: PropTypes.func, + displayWarning: PropTypes.func, + revealSeedConfirmation: PropTypes.func, + setFeatureFlagToBeta: PropTypes.func, + showResetAccountConfirmationModal: PropTypes.func, + warning: PropTypes.string, + history: PropTypes.object, + isMascara: PropTypes.bool, + updateCurrentLocale: PropTypes.func, + currentLocale: PropTypes.string, + useBlockie: PropTypes.bool, + sendHexData: PropTypes.bool, + currentCurrency: PropTypes.string, + conversionDate: PropTypes.number, + } + + state = { + newRpc: '', + } + + renderCurrentConversion () { + const { t } = this.context + const { currentCurrency, conversionDate, setCurrentCurrency } = this.props + + return ( +
+
+ { t('currentConversion') } + + { `Updated ${Date(conversionDate)}` } + +
+
+
+ setCurrentCurrency(newCurrency)} + /> +
+
+
+ ) + } + + renderCurrentLocale () { + const { t } = this.context + const { updateCurrentLocale, currentLocale } = this.props + const currentLocaleMeta = locales.find(locale => locale.code === currentLocale) + const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' + + return ( +
+
+ + { t('currentLanguage') } + + + { currentLocaleName } + +
+
+
+ updateCurrentLocale(newLocale)} + /> +
+
+
+ ) + } + + renderNewRpcUrl () { + const { t } = this.context + const { newRpc } = this.state + + return ( +
+
+ { t('newRPC') } +
+
+
+ this.setState({ newRpc: e.target.value })} + onKeyPress={e => { + if (e.key === 'Enter') { + this.validateRpc(newRpc) + } + }} + fullWidth + margin="none" + /> +
{ + e.preventDefault() + this.validateRpc(newRpc) + }} + > + { t('save') } +
+
+
+
+ ) + } + + validateRpc (newRpc) { + const { setRpcTarget, displayWarning } = this.props + + if (validUrl.isWebUri(newRpc)) { + setRpcTarget(newRpc) + } else { + const appendedRpc = `http://${newRpc}` + + if (validUrl.isWebUri(appendedRpc)) { + displayWarning(this.context.t('uriErrorMsg')) + } else { + displayWarning(this.context.t('invalidRPC')) + } + } + } + + renderStateLogs () { + const { t } = this.context + const { displayWarning } = this.props + + return ( +
+
+ { t('stateLogs') } + + { t('stateLogsDescription') } + +
+
+
+ +
+
+
+ ) + } + + renderSeedWords () { + const { t } = this.context + const { history } = this.props + + return ( +
+
+ { t('revealSeedWords') } +
+
+
+ +
+
+
+ ) + } + + renderOldUI () { + const { t } = this.context + const { setFeatureFlagToBeta } = this.props + + return ( +
+
+ { t('useOldUI') } +
+
+
+ +
+
+
+ ) + } + + renderResetAccount () { + const { t } = this.context + const { showResetAccountConfirmationModal } = this.props + + return ( +
+
+ { t('resetAccount') } +
+
+
+ +
+
+
+ ) + } + + renderBlockieOptIn () { + const { useBlockie, setUseBlockie } = this.props + + return ( +
+
+ { this.context.t('blockiesIdenticon') } +
+
+
+ setUseBlockie(!value)} + activeLabel="" + inactiveLabel="" + /> +
+
+
+ ) + } + + renderHexDataOptIn () { + const { t } = this.context + const { sendHexData, setHexDataFeatureFlag } = this.props + + return ( +
+
+ { t('showHexData') } +
+ { t('showHexDataDescription') } +
+
+
+
+ setHexDataFeatureFlag(!value)} + activeLabel="" + inactiveLabel="" + /> +
+
+
+ ) + } + + render () { + const { warning, isMascara } = this.props + + return ( +
+ { warning &&
{ warning }
} + { this.renderCurrentConversion() } + { this.renderCurrentLocale() } + { this.renderNewRpcUrl() } + { this.renderStateLogs() } + { this.renderSeedWords() } + { !isMascara && this.renderOldUI() } + { this.renderResetAccount() } + { this.renderBlockieOptIn() } + { this.renderHexDataOptIn() } +
+ ) + } +} diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.container.js b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js new file mode 100644 index 000000000..665b56f5c --- /dev/null +++ b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js @@ -0,0 +1,59 @@ +import SettingsTab from './settings-tab.component' +import { compose } from 'recompose' +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { + setCurrentCurrency, + setRpcTarget, + displayWarning, + revealSeedConfirmation, + setUseBlockie, + updateCurrentLocale, + setFeatureFlag, + showModal, +} from '../../../../actions' + +const mapStateToProps = state => { + const { appState: { warning }, metamask } = state + const { + currentCurrency, + conversionDate, + useBlockie, + featureFlags: { sendHexData } = {}, + provider = {}, + isMascara, + currentLocale, + } = metamask + + return { + warning, + isMascara, + currentLocale, + currentCurrency, + conversionDate, + useBlockie, + sendHexData, + provider, + } +} + +const mapDispatchToProps = dispatch => { + return { + setCurrentCurrency: currency => dispatch(setCurrentCurrency(currency)), + setRpcTarget: newRpc => dispatch(setRpcTarget(newRpc)), + displayWarning: warning => dispatch(displayWarning(warning)), + revealSeedConfirmation: () => dispatch(revealSeedConfirmation()), + setUseBlockie: value => dispatch(setUseBlockie(value)), + updateCurrentLocale: key => dispatch(updateCurrentLocale(key)), + setFeatureFlagToBeta: () => { + return dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + }, + setHexDataFeatureFlag: shouldShow => dispatch(setFeatureFlag('sendHexData', shouldShow)), + showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })), + } +} + +export default compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(SettingsTab) diff --git a/ui/app/components/pages/settings/settings.component.js b/ui/app/components/pages/settings/settings.component.js new file mode 100644 index 000000000..94a97bba1 --- /dev/null +++ b/ui/app/components/pages/settings/settings.component.js @@ -0,0 +1,54 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import { Switch, Route, matchPath } from 'react-router-dom' +import TabBar from '../../tab-bar' +import SettingsTab from './settings-tab' +import InfoTab from './info-tab' +import { DEFAULT_ROUTE, SETTINGS_ROUTE, INFO_ROUTE } from '../../../routes' + +export default class SettingsPage extends PureComponent { + static propTypes = { + location: PropTypes.object, + history: PropTypes.object, + t: PropTypes.func, + } + + static contextTypes = { + t: PropTypes.func, + } + + render () { + const { history, location } = this.props + + return ( +
+
+
history.push(DEFAULT_ROUTE)} + /> + matchPath(location.pathname, { path: key, exact: true })} + onSelect={key => history.push(key)} + /> +
+ + + + +
+ ) + } +} diff --git a/ui/app/components/pages/settings/settings.js b/ui/app/components/pages/settings/settings.js deleted file mode 100644 index 423276cf3..000000000 --- a/ui/app/components/pages/settings/settings.js +++ /dev/null @@ -1,408 +0,0 @@ -const { Component } = require('react') -const { withRouter } = require('react-router-dom') -const { compose } = require('recompose') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const connect = require('react-redux').connect -const actions = require('../../../actions') -const infuraCurrencies = require('../../../infura-conversion.json') -const validUrl = require('valid-url') -const { exportAsFile } = require('../../../util') -const SimpleDropdown = require('../../dropdowns/simple-dropdown') -const ToggleButton = require('react-toggle-button') -const { REVEAL_SEED_ROUTE } = require('../../../routes') -const locales = require('../../../../../app/_locales/index.json') - -import Button from '../../button' - -const getInfuraCurrencyOptions = () => { - const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { - return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase()) - }) - - return sortedCurrencies.map(({ quote: { code, name } }) => { - return { - displayValue: `${code.toUpperCase()} - ${name}`, - key: code, - value: code, - } - }) -} - -const getLocaleOptions = () => { - return locales.map((locale) => { - return { - displayValue: `${locale.name}`, - key: locale.code, - value: locale.code, - } - }) -} - -class Settings extends Component { - constructor (props) { - super(props) - - this.state = { - newRpc: '', - } - } - - renderBlockieOptIn () { - const { metamask: { useBlockie }, setUseBlockie } = this.props - - return h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('span', this.context.t('blockiesIdenticon')), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(ToggleButton, { - value: useBlockie, - onToggle: (value) => setUseBlockie(!value), - activeLabel: '', - inactiveLabel: '', - }), - ]), - ]), - ]) - } - - renderHexDataOptIn () { - const { metamask: { featureFlags: { sendHexData } }, setHexDataFeatureFlag } = this.props - - return h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('span', this.context.t('showHexData')), - h( - 'div.settings__content-description', - this.context.t('showHexDataDescription') - ), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(ToggleButton, { - value: sendHexData, - onToggle: (value) => setHexDataFeatureFlag(!value), - activeLabel: '', - inactiveLabel: '', - }), - ]), - ]), - ]) - } - - renderCurrentConversion () { - const { metamask: { currentCurrency, conversionDate }, setCurrentCurrency } = this.props - - return h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('span', this.context.t('currentConversion')), - h('span.settings__content-description', `Updated ${Date(conversionDate)}`), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(SimpleDropdown, { - placeholder: this.context.t('selectCurrency'), - options: getInfuraCurrencyOptions(), - selectedOption: currentCurrency, - onSelect: newCurrency => setCurrentCurrency(newCurrency), - }), - ]), - ]), - ]) - } - - renderCurrentLocale () { - const { updateCurrentLocale, currentLocale } = this.props - const currentLocaleMeta = locales.find(locale => locale.code === currentLocale) - const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' - - return h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('span', 'Current Language'), - h('span.settings__content-description', `${currentLocaleName}`), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(SimpleDropdown, { - placeholder: 'Select Locale', - options: getLocaleOptions(), - selectedOption: currentLocale, - onSelect: async (newLocale) => { - updateCurrentLocale(newLocale) - }, - }), - ]), - ]), - ]) - } - - renderCurrentProvider () { - const { metamask: { provider = {} } } = this.props - let title, value, color - - switch (provider.type) { - - case 'mainnet': - title = this.context.t('currentNetwork') - value = this.context.t('mainnet') - color = '#038789' - break - - case 'ropsten': - title = this.context.t('currentNetwork') - value = this.context.t('ropsten') - color = '#e91550' - break - - case 'kovan': - title = this.context.t('currentNetwork') - value = this.context.t('kovan') - color = '#690496' - break - - case 'rinkeby': - title = this.context.t('currentNetwork') - value = this.context.t('rinkeby') - color = '#ebb33f' - break - - default: - title = this.context.t('currentRpc') - value = provider.rpcTarget - } - - return h('div.settings__content-row', [ - h('div.settings__content-item', title), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h('div.settings__provider-wrapper', [ - h('div.settings__provider-icon', { style: { background: color } }), - h('div', value), - ]), - ]), - ]), - ]) - } - - renderNewRpcUrl () { - return ( - h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('span', this.context.t('newRPC')), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h('input.settings__input', { - placeholder: this.context.t('newRPC'), - onChange: event => this.setState({ newRpc: event.target.value }), - onKeyPress: event => { - if (event.key === 'Enter') { - this.validateRpc(this.state.newRpc) - } - }, - }), - h('div.settings__rpc-save-button', { - onClick: event => { - event.preventDefault() - this.validateRpc(this.state.newRpc) - }, - }, this.context.t('save')), - ]), - ]), - ]) - ) - } - - validateRpc (newRpc) { - const { setRpcTarget, displayWarning } = this.props - - if (validUrl.isWebUri(newRpc)) { - setRpcTarget(newRpc) - } else { - const appendedRpc = `http://${newRpc}` - - if (validUrl.isWebUri(appendedRpc)) { - displayWarning(this.context.t('uriErrorMsg')) - } else { - displayWarning(this.context.t('invalidRPC')) - } - } - } - - renderStateLogs () { - return ( - h('div.settings__content-row', [ - h('div.settings__content-item', [ - h('div', this.context.t('stateLogs')), - h( - 'div.settings__content-description', - this.context.t('stateLogsDescription') - ), - ]), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(Button, { - type: 'primary', - large: true, - className: 'settings__button', - onClick (event) { - window.logStateString((err, result) => { - if (err) { - this.state.dispatch(actions.displayWarning(this.context.t('stateLogError'))) - } else { - exportAsFile('MetaMask State Logs.json', result) - } - }) - }, - }, this.context.t('downloadStateLogs')), - ]), - ]), - ]) - ) - } - - renderSeedWords () { - const { history } = this.props - - return ( - h('div.settings__content-row', [ - h('div.settings__content-item', this.context.t('revealSeedWords')), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(Button, { - type: 'primary', - large: true, - className: 'settings__button--red', - onClick: event => { - event.preventDefault() - history.push(REVEAL_SEED_ROUTE) - }, - }, this.context.t('revealSeedWords')), - ]), - ]), - ]) - ) - } - - renderOldUI () { - const { setFeatureFlagToBeta } = this.props - - return ( - h('div.settings__content-row', [ - h('div.settings__content-item', this.context.t('useOldUI')), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(Button, { - type: 'primary', - large: true, - className: 'settings__button--orange', - onClick (event) { - event.preventDefault() - setFeatureFlagToBeta() - }, - }, this.context.t('useOldUI')), - ]), - ]), - ]) - ) - } - - renderResetAccount () { - const { showResetAccountConfirmationModal } = this.props - - return h('div.settings__content-row', [ - h('div.settings__content-item', this.context.t('resetAccount')), - h('div.settings__content-item', [ - h('div.settings__content-item-col', [ - h(Button, { - type: 'primary', - large: true, - className: 'settings__button--orange', - onClick (event) { - event.preventDefault() - showResetAccountConfirmationModal() - }, - }, this.context.t('resetAccount')), - ]), - ]), - ]) - } - - render () { - const { warning, isMascara } = this.props - - return ( - h('div.settings__content', [ - warning && h('div.settings__error', warning), - this.renderCurrentConversion(), - this.renderCurrentLocale(), - // this.renderCurrentProvider(), - this.renderNewRpcUrl(), - this.renderStateLogs(), - this.renderSeedWords(), - !isMascara && this.renderOldUI(), - this.renderResetAccount(), - this.renderBlockieOptIn(), - this.renderHexDataOptIn(), - ]) - ) - } -} - -Settings.propTypes = { - metamask: PropTypes.object, - setUseBlockie: PropTypes.func, - setHexDataFeatureFlag: PropTypes.func, - setCurrentCurrency: PropTypes.func, - setRpcTarget: PropTypes.func, - displayWarning: PropTypes.func, - revealSeedConfirmation: PropTypes.func, - setFeatureFlagToBeta: PropTypes.func, - showResetAccountConfirmationModal: PropTypes.func, - warning: PropTypes.string, - history: PropTypes.object, - isMascara: PropTypes.bool, - updateCurrentLocale: PropTypes.func, - currentLocale: PropTypes.string, - t: PropTypes.func, -} - -const mapStateToProps = state => { - return { - metamask: state.metamask, - warning: state.appState.warning, - isMascara: state.metamask.isMascara, - currentLocale: state.metamask.currentLocale, - } -} - -const mapDispatchToProps = dispatch => { - return { - setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)), - setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), - displayWarning: warning => dispatch(actions.displayWarning(warning)), - revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), - setUseBlockie: value => dispatch(actions.setUseBlockie(value)), - updateCurrentLocale: key => dispatch(actions.updateCurrentLocale(key)), - setFeatureFlagToBeta: () => { - return dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) - }, - setHexDataFeatureFlag: (featureFlagShowState) => { - return dispatch(actions.setFeatureFlag('sendHexData', featureFlagShowState)) - }, - showResetAccountConfirmationModal: () => { - return dispatch(actions.showModal({ name: 'CONFIRM_RESET_ACCOUNT' })) - }, - } -} - -Settings.contextTypes = { - t: PropTypes.func, -} - -module.exports = compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps) -)(Settings) diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 9e2008b54..99deaf918 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -36,8 +36,6 @@ @import './gas-slider.scss'; -@import './settings.scss'; - @import './tab-bar.scss'; @import './simple-dropdown.scss'; diff --git a/ui/app/css/itcss/components/settings.scss b/ui/app/css/itcss/components/settings.scss deleted file mode 100644 index 0dd61ac5e..000000000 --- a/ui/app/css/itcss/components/settings.scss +++ /dev/null @@ -1,214 +0,0 @@ -.settings { - position: relative; - background: $white; - display: flex; - flex-flow: column nowrap; -} - -.settings__header { - padding: 25px; -} - -.settings__close-button::after { - content: '\00D7'; - font-size: 40px; - color: $dusty-gray; - position: absolute; - top: 25px; - right: 30px; - cursor: pointer; -} - -.settings__error { - padding-bottom: 20px; - text-align: center; - color: $crimson; -} - -.settings__content { - padding: 0 25px; - height: auto; - overflow: auto; -} - -.settings__content-row { - display: flex; - flex-direction: row; - padding: 10px 0 20px; - - @media screen and (max-width: 575px) { - flex-direction: column; - padding: 10px 0; - } -} - -.settings__content-item { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; - padding: 0 5px; - height: 71px; - - @media screen and (max-width: 575px) { - height: initial; - padding: 5px 0; - } - - &--without-height { - height: initial; - } -} - -.settings__content-item-col { - max-width: 300px; - display: flex; - flex-direction: column; - - @media screen and (max-width: 575px) { - max-width: 100%; - width: 100%; - } -} - -.settings__content-description { - font-size: 14px; - color: $dusty-gray; - padding-top: 5px; -} - -.settings__input { - padding-left: 10px; - font-size: 14px; - height: 40px; - border: 1px solid $alto; -} - -.settings__input::-webkit-input-placeholder { - font-weight: 100; - color: $dusty-gray; -} - -.settings__input::-moz-placeholder { - font-weight: 100; - color: $dusty-gray; -} - -.settings__input:-ms-input-placeholder { - font-weight: 100; - color: $dusty-gray; -} - -.settings__input:-moz-placeholder { - font-weight: 100; - color: $dusty-gray; -} - -.settings__provider-wrapper { - font-size: 16px; - border: 1px solid $alto; - border-radius: 2px; - padding: 15px; - background-color: $white; - display: flex; - align-items: center; - justify-content: flex-start; -} - -.settings__provider-icon { - height: 10px; - width: 10px; - margin-right: 10px; - border-radius: 10px; -} - -.settings__rpc-save-button { - align-self: flex-end; - padding: 5px; - text-transform: uppercase; - color: $dusty-gray; - cursor: pointer; -} - -.settings__button--red { - border-color: lighten($monzo, 10%); - color: $monzo; - - &:active { - background: lighten($monzo, 55%); - border-color: $monzo; - } - - &:hover { - border-color: $monzo; - } -} - -.settings__button--orange { - border-color: lighten($ecstasy, 20%); - color: $ecstasy; - - &:active { - background: lighten($ecstasy, 40%); - border-color: $ecstasy; - } - - &:hover { - border-color: $ecstasy; - } -} - -.settings__info-logo-wrapper { - height: 80px; - margin-bottom: 20px; -} - -.settings__info-logo { - max-height: 100%; - max-width: 100%; -} - -.settings__info-item { - padding: 10px 0; -} - -.settings__info-link-header { - padding-bottom: 15px; - - @media screen and (max-width: 575px) { - padding-bottom: 5px; - } -} - -.settings__info-link-item { - padding: 15px 0; - - @media screen and (max-width: 575px) { - padding: 5px 0; - } -} - -.settings__info-version-number { - padding-top: 5px; - font-size: 13px; - color: $dusty-gray; -} - -.settings__info-about { - color: $dusty-gray; - margin-bottom: 15px; -} - -.settings__info-link { - color: $curious-blue; -} - -.settings__info-separator { - margin: 15px 0; - width: 80px; - border-color: $alto; - border: none; - height: 1px; - background-color: $alto; - color: $alto; -} -- cgit v1.2.3 From 9088fd1de49197d0e436f989c6698f2d4c36d456 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 19 Sep 2018 16:55:58 -0700 Subject: Add Current Conversion Updated string to translations --- app/_locales/en/messages.json | 3 +++ .../components/pages/settings/settings-tab/settings-tab.component.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 359eee9ef..779608809 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1197,6 +1197,9 @@ "unlockMessage": { "message": "The decentralized web awaits" }, + "updatedWithDate": { + "message": "Updated $1" + }, "uriErrorMsg": { "message": "URIs require the appropriate HTTP/HTTPS prefix." }, diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js index 543bd0bcc..53c4f16e0 100644 --- a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js @@ -69,7 +69,7 @@ export default class SettingsTab extends PureComponent {
{ t('currentConversion') } - { `Updated ${Date(conversionDate)}` } + { t('updatedWithDate', [Date(conversionDate)]) }
-- cgit v1.2.3 From 01166b26edc5b979e5cbc7fe76df6fbfc272bea7 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 20 Sep 2018 15:53:53 -0700 Subject: Fix translation casing --- app/_locales/en/messages.json | 4 ++-- ui/app/components/pages/settings/info-tab/index.scss | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 779608809..951e24ec1 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -217,7 +217,7 @@ "message": "Current Conversion" }, "currentLanguage": { - "message": "current language" + "message": "Current Language" }, "currentNetwork": { "message": "Current Network" @@ -600,7 +600,7 @@ "message": "MetaMask Seed Words" }, "metamaskVersion": { - "message": "metamask version" + "message": "MetaMask Version" }, "min": { "message": "Minimum" diff --git a/ui/app/components/pages/settings/info-tab/index.scss b/ui/app/components/pages/settings/info-tab/index.scss index 00342dc5f..43ad6f652 100644 --- a/ui/app/components/pages/settings/info-tab/index.scss +++ b/ui/app/components/pages/settings/info-tab/index.scss @@ -33,10 +33,6 @@ color: $curious-blue; } - &__version-header { - text-transform: capitalize; - } - &__version-number { padding-top: 5px; font-size: 13px; -- cgit v1.2.3