mirror of
https://github.com/zoriya/flood.git
synced 2026-06-06 12:02:13 +00:00
Merge pull request #65 from jfurrow/feature/allow-language-changes
Allow language changes within SettingsModal
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
$form--label--foreground: desaturate(lighten(#5c7087, 3%), 3%);
|
||||
|
||||
$form--element--border-radius: 4px;
|
||||
|
||||
$textbox--background: #242b36;
|
||||
$textbox--foreground: #5e728c;
|
||||
$textbox--placeholder: #424d5e;
|
||||
@@ -76,7 +78,7 @@ $interacative-list--item--icon--fill--hover: rgba(lighten($interacative-list--it
|
||||
|
||||
.textbox {
|
||||
background: $textbox--background;
|
||||
border-radius: 4px;
|
||||
border-radius: $form--element--border-radius;
|
||||
border: 1px solid $textbox--border;
|
||||
color: $textbox--foreground;
|
||||
display: block;
|
||||
@@ -119,7 +121,7 @@ $interacative-list--item--icon--fill--hover: rgba(lighten($interacative-list--it
|
||||
.button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
border-radius: $form--element--border-radius;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
padding: 8px 22px;
|
||||
@@ -253,7 +255,7 @@ $interacative-list--item--icon--fill--hover: rgba(lighten($interacative-list--it
|
||||
.interactive-list {
|
||||
@extend .textbox;
|
||||
@extend .textbox.is-fulfilled;
|
||||
border-radius: 4px;
|
||||
border-radius: $form--element--border-radius;
|
||||
color: $interacative-list--item--foreground;
|
||||
padding: $spacing-unit * 1/2;
|
||||
|
||||
@@ -384,6 +386,31 @@ $interacative-list--item--icon--fill--hover: rgba(lighten($interacative-list--it
|
||||
justify-content: center;
|
||||
padding-top: $spacing-unit * 3/5;
|
||||
}
|
||||
|
||||
& > .dropdown {
|
||||
|
||||
& > .dropdown {
|
||||
|
||||
&__trigger {
|
||||
|
||||
.dropdown {
|
||||
|
||||
&__button {
|
||||
@extend .button--deemphasize;
|
||||
border-radius: $form--element--border-radius;
|
||||
transition: background 0.25s, color 0.25s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
|
||||
&__button {
|
||||
padding-top: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__actions {
|
||||
|
||||
+56
-14
@@ -5,32 +5,74 @@ import ReactDOM from 'react-dom';
|
||||
|
||||
import * as i18n from './i18n';
|
||||
import Application from './components/Layout/Application';
|
||||
import EventTypes from './constants/EventTypes';
|
||||
import Login from './views/Login';
|
||||
import Register from './views/Register';
|
||||
import SettingsStore from './stores/SettingsStore';
|
||||
import TorrentList from './views/TorrentList';
|
||||
import UIStore from './stores/UIStore';
|
||||
|
||||
let appRoutes = (
|
||||
<Router history={browserHistory}>
|
||||
<Route path="/" component={Application}>
|
||||
<IndexRoute component={Login} />
|
||||
<Route path="login" component={Login} />
|
||||
<Route path="register" component={Register} />
|
||||
<Route path="list" component={TorrentList} />
|
||||
<Route path="*" component={Login} />
|
||||
</Route>
|
||||
</Router>
|
||||
);
|
||||
|
||||
const METHODS_TO_BIND = ['handleSettingsChange'];
|
||||
|
||||
class FloodApp extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
locale: SettingsStore.getFloodSettings('language')
|
||||
};
|
||||
|
||||
METHODS_TO_BIND.forEach((method) => {
|
||||
this[method] = this[method].bind(this);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
UIStore.registerDependency('flood-settings');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
SettingsStore.listen(EventTypes.SETTINGS_CHANGE,
|
||||
this.handleSettingsChange);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
SettingsStore.unlisten(EventTypes.SETTINGS_CHANGE,
|
||||
this.handleSettingsChange);
|
||||
}
|
||||
|
||||
handleSettingsChange() {
|
||||
if (SettingsStore.getFloodSettings('language') !== this.state.language) {
|
||||
this.setState({locale: SettingsStore.getFloodSettings('language')});
|
||||
}
|
||||
|
||||
UIStore.satisfyDependency('flood-settings');
|
||||
}
|
||||
|
||||
render() {
|
||||
let {locale} = this.state;
|
||||
|
||||
return (
|
||||
<Router history={browserHistory}>
|
||||
<Route path="/" component={Application}>
|
||||
<IndexRoute component={Login} />
|
||||
<Route path="login" component={Login} />
|
||||
<Route path="register" component={Register} />
|
||||
<Route path="list" component={TorrentList} />
|
||||
<Route path="*" component={Login} />
|
||||
</Route>
|
||||
</Router>
|
||||
<IntlProvider locale={locale} messages={i18n[locale]}>
|
||||
{appRoutes}
|
||||
</IntlProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let locale = SettingsStore.getFloodSettings('language');
|
||||
|
||||
ReactDOM.render(
|
||||
<IntlProvider locale={locale} messages={i18n[locale]}>
|
||||
<FloodApp />
|
||||
</IntlProvider>,
|
||||
<FloodApp />,
|
||||
document.getElementById('app')
|
||||
);
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import _ from 'lodash';
|
||||
import {formatMessage, FormattedMessage, injectIntl} from 'react-intl';
|
||||
import React from 'react';
|
||||
|
||||
import AuthStore from '../../../stores/AuthStore';
|
||||
import Checkbox from '../../General/FormElements/Checkbox';
|
||||
import Close from '../../Icons/Close';
|
||||
import Dropdown from '../../General/FormElements/Dropdown';
|
||||
import EventTypes from '../../../constants/EventTypes';
|
||||
import Languages from '../../../constants/Languages';
|
||||
import SettingsStore from '../../../stores/SettingsStore';
|
||||
import SettingsTab from './SettingsTab';
|
||||
|
||||
const METHODS_TO_BIND = [
|
||||
'handleItemSelect'
|
||||
];
|
||||
|
||||
class UITab extends SettingsTab {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.state = {
|
||||
selectedLanguage: SettingsStore.getFloodSettings('language')
|
||||
};
|
||||
|
||||
METHODS_TO_BIND.forEach((method) => {
|
||||
this[method] = this[method].bind(this);
|
||||
});
|
||||
}
|
||||
|
||||
getDropdownHeader() {
|
||||
return (
|
||||
<a className="dropdown__button">
|
||||
<span className="dropdown__value">
|
||||
<FormattedMessage
|
||||
defaultMessage={Languages[this.state.selectedLanguage].defaultMessage}
|
||||
id={Languages[this.state.selectedLanguage].id} />
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
getDropdownMenu() {
|
||||
let items = Object.keys(Languages).map((language) => {
|
||||
return {
|
||||
displayName: this.props.intl.formatMessage(
|
||||
Languages[language]
|
||||
),
|
||||
selected: this.state.selectedLanguage === language,
|
||||
language
|
||||
};
|
||||
});
|
||||
|
||||
// Dropdown expects an array of arrays.
|
||||
return [items];
|
||||
}
|
||||
|
||||
handleItemSelect(item) {
|
||||
let {language} = item;
|
||||
|
||||
this.setState({selectedLanguage: language});
|
||||
this.props.onSettingsChange({language});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="form">
|
||||
<div className="form__section">
|
||||
<div className="form__section__heading">
|
||||
<FormattedMessage
|
||||
defaultMessage="Locale"
|
||||
id="settings.ui.locale" />
|
||||
</div>
|
||||
<div className="form__row">
|
||||
<div className="form__column form__column--auto">
|
||||
<label className="form__label">
|
||||
<FormattedMessage
|
||||
defaultMessage="Language"
|
||||
id="settings.ui.language" />
|
||||
</label>
|
||||
<Dropdown
|
||||
handleItemSelect={this.handleItemSelect}
|
||||
header={this.getDropdownHeader()}
|
||||
menuItems={this.getDropdownMenu()} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(UITab);
|
||||
@@ -11,6 +11,7 @@ import LoadingIndicatorDots from '../../Icons/LoadingIndicatorDots';
|
||||
import Modal from '../Modal';
|
||||
import ResourcesTab from './ResourcesTab';
|
||||
import SettingsStore from '../../../stores/SettingsStore';
|
||||
import UITab from './UITab';
|
||||
|
||||
const METHODS_TO_BIND = [
|
||||
'handleClientSettingsChange',
|
||||
@@ -213,6 +214,16 @@ class SettingsModal extends React.Component {
|
||||
id: 'settings.tabs.authentication',
|
||||
defaultMessage: 'Authentication'
|
||||
})
|
||||
},
|
||||
ui: {
|
||||
content: UITab,
|
||||
label: this.props.intl.formatMessage({
|
||||
id: 'settings.tabs.userinterface',
|
||||
defaultMessage: 'User Interface'
|
||||
}),
|
||||
props: {
|
||||
onSettingsChange: this.handleFloodSettingsChange
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
const Languages = {
|
||||
en: {
|
||||
defaultMessage: 'English',
|
||||
id: 'locale.language.en'
|
||||
},
|
||||
nl: {
|
||||
defaultMessage: 'Nederlands',
|
||||
id: 'locale.language.nl'
|
||||
}
|
||||
};
|
||||
|
||||
export default Languages;
|
||||
@@ -93,7 +93,9 @@ class SettingsStoreClass extends BaseStore {
|
||||
this.fetchStatus.floodSettingsFetched = true;
|
||||
|
||||
Object.keys(settings).forEach((property) => {
|
||||
this.floodSettings[property] = settings[property];
|
||||
if (settings[property] != null) {
|
||||
this.floodSettings[property] = settings[property];
|
||||
}
|
||||
});
|
||||
|
||||
this.emit(EventTypes.SETTINGS_FETCH_REQUEST_SUCCESS);
|
||||
|
||||
Reference in New Issue
Block a user