settings on redux; some fix with theme

This commit is contained in:
2020-10-15 00:34:37 +03:00
parent 5d137eb603
commit 19e023c80f
9 changed files with 75 additions and 35 deletions
+10 -6
View File
@@ -26,11 +26,13 @@ import Users from "../Users/Users";
import {getVersion, version} from "../../api/api"; import {getVersion, version} from "../../api/api";
import Settings from "../User/Settings/Settings"; import Settings from "../User/Settings/Settings";
import {setUser} from "../../store/ducks/currentUser"; import {setUser} from "../../store/ducks/currentUser";
import {setSettings} from "../../store/ducks/userSettings";
type Props = { type Props = {
notifications: React.ReactNode[] notifications: React.ReactNode[]
setUser: (user: UserType) => void
modal: React.ReactNode modal: React.ReactNode
setUser: SetUser
setSettings: SetSettings
}; };
type State = {} type State = {}
@@ -45,10 +47,11 @@ class App extends React.Component<Props, State> {
if(cachedTheme) if(cachedTheme)
document.body.setAttribute('theme', cachedTheme); document.body.setAttribute('theme', cachedTheme);
const { setUser } = props; const { setUser, setSettings } = props;
fetchCurrentUser().then((user: UserType) => { fetchCurrentUser().then(user => {
setUser(user); setUser(user);
fetchUserSettings().then((settings: UserSettingsType) => { fetchUserSettings().then(settings => {
setSettings(settings);
if(settings.theme !== cachedTheme) { if(settings.theme !== cachedTheme) {
localStorage.setItem('theme', settings.theme); localStorage.setItem('theme', settings.theme);
document.body.setAttribute('theme', settings.theme); document.body.setAttribute('theme', settings.theme);
@@ -64,7 +67,7 @@ class App extends React.Component<Props, State> {
getVersion().then(res => { getVersion().then(res => {
if(version !== res.version) { if(version !== res.version) {
console.log(`Current back-end version: ${res.version}. Clearing cache`); console.debug(`Current back-end version: ${res.version}. Clearing cache`);
caches.keys().then(names => { caches.keys().then(names => {
names.forEach(name => caches.delete(name).catch(console.error)) names.forEach(name => caches.delete(name).catch(console.error))
@@ -130,6 +133,7 @@ export default connect(
modal: state.modal modal: state.modal
}), }),
dispatch => ({ dispatch => ({
setUser: (userData: UserType) => dispatch(setUser(userData)) setUser: (userData: UserType) => dispatch(setUser(userData)),
setSettings: (settings: UserSettingsType) => dispatch(setSettings(settings))
}) })
)(App); )(App);
+16 -7
View File
@@ -13,12 +13,15 @@ import Input from "../../ui/Input/Input";
import {setUser} from "../../store/ducks/currentUser"; import {setUser} from "../../store/ducks/currentUser";
import {addNotification} from "../../store/ducks/notifications"; import {addNotification} from "../../store/ducks/notifications";
import {hideModal, setModal} from "../../store/ducks/modal"; import {hideModal, setModal} from "../../store/ducks/modal";
import {fetchUserSettings} from "../../api/users";
import {setSettings} from "../../store/ducks/userSettings";
type Props = { type Props = {
setUser: (user: UserType) => void setUser: SetUser
addNotification: (notification: React.ReactNode) => void addNotification: AddNotification
setModal: (modal: React.ReactNode | null) => void setModal: SetModal
hideModal: () => void hideModal: HideModal
setSettings: SetSettings
}; };
type State = { type State = {
@@ -36,7 +39,7 @@ class LoginModal extends React.Component<Props, State> {
loginAndFetchToken = (event: FormEvent) => { loginAndFetchToken = (event: FormEvent) => {
event.preventDefault(); event.preventDefault();
const { setUser, addNotification, setModal } = this.props; const { setUser, addNotification, setModal, setSettings } = this.props;
const { login: log, password, recaptcha } = this.state; const { login: log, password, recaptcha } = this.state;
login(log, password, recaptcha).then(user => { login(log, password, recaptcha).then(user => {
@@ -50,8 +53,13 @@ class LoginModal extends React.Component<Props, State> {
); );
addNotification(successful); addNotification(successful);
setModal(null); setModal(null);
})
.catch((r: ApiError) => { fetchUserSettings().then(settings => {
localStorage.setItem('theme', settings.theme);
document.body.setAttribute('theme', settings.theme);
setSettings(settings);
});
}).catch((r: ApiError) => {
this.setState({ error: errors[r.code] }); this.setState({ error: errors[r.code] });
if(r.code === 9) this.setState({ recaptchaNeeded: true }); if(r.code === 9) this.setState({ recaptchaNeeded: true });
}); });
@@ -105,6 +113,7 @@ class LoginModal extends React.Component<Props, State> {
export default connect(null, export default connect(null,
dispatch => ({ dispatch => ({
setUser: (user: UserType) => dispatch(setUser(user)), setUser: (user: UserType) => dispatch(setUser(user)),
setSettings: (settings: UserSettingsType) => dispatch(setSettings(settings)),
addNotification: (notification: React.ReactNode) => dispatch(addNotification(notification)), addNotification: (notification: React.ReactNode) => dispatch(addNotification(notification)),
setModal: (modal: React.ReactNode | null) => dispatch(setModal(modal)), setModal: (modal: React.ReactNode | null) => dispatch(setModal(modal)),
hideModal: () => dispatch(hideModal()) hideModal: () => dispatch(hideModal())
+3 -1
View File
@@ -30,7 +30,9 @@ class Navbar extends React.Component<Props, State> {
logout = () => { logout = () => {
this.props.logout(); this.props.logout();
localStorage.removeItem('user'); localStorage.removeItem('user');
userLogout().then(); localStorage.removeItem('theme');
document.querySelector('body')!!.removeAttribute('theme');
userLogout().catch(() => {});
}; };
changeSize = () => { changeSize = () => {
+7 -9
View File
@@ -1,12 +1,13 @@
import Button from "../../../ui/Button/Button"; import Button from "../../../ui/Button/Button";
import Group from "../../../ui/Group/Group"; import Group from "../../../ui/Group/Group";
import React, {FormEvent} from "react"; import React, {FormEvent} from "react";
import {fetchUserSettings, updateUserAppearanceSettings} from "../../../api/users"; import {updateUserAppearanceSettings} from "../../../api/users";
import {connect} from "react-redux"; import {connect} from "react-redux";
import {setUser} from "../../../store/ducks/currentUser"; import {setUser} from "../../../store/ducks/currentUser";
type Props = { type Props = {
setUser: SetUser setUser: SetUser
settings: UserSettingsType
} }
type State = { type State = {
@@ -15,13 +16,7 @@ type State = {
class Appearance extends React.Component<Props, State> { class Appearance extends React.Component<Props, State> {
state: State = { state: State = {
theme: 'dark' theme: this.props.settings.theme
}
componentDidMount() {
fetchUserSettings().then(settings => {
this.setState({ theme: settings.theme })
})
} }
saveTheme = (event: FormEvent) => { saveTheme = (event: FormEvent) => {
@@ -59,7 +54,10 @@ class Appearance extends React.Component<Props, State> {
} }
} }
export default connect(null, export default connect(
(state: StoreState) => ({
settings: state.userSettings
}),
dispatch => ({ dispatch => ({
setUser: (user: UserType) => dispatch(setUser(user)) setUser: (user: UserType) => dispatch(setUser(user))
}) })
+10 -10
View File
@@ -1,10 +1,12 @@
import React, {ChangeEvent, FormEvent} from "react"; import React, {ChangeEvent, FormEvent} from "react";
import Button from "../../../ui/Button/Button"; import Button from "../../../ui/Button/Button";
import Group from "../../../ui/Group/Group"; import Group from "../../../ui/Group/Group";
import {fetchUserSettings, updateUserGeneralSettings, uploadAvatar} from "../../../api/users"; import {updateUserGeneralSettings, uploadAvatar} from "../../../api/users";
import {connect} from "react-redux";
type Props = { type Props = {
setUser: (user: UserType) => void setUser: SetUser
settings: UserSettingsType
} }
type State = { type State = {
@@ -15,13 +17,7 @@ type State = {
class General extends React.Component<Props, State> { class General extends React.Component<Props, State> {
state: State = { state: State = {
useGravatar: false, avatar: null useGravatar: this.props.settings.use_gravatar, avatar: null
}
componentDidMount() {
fetchUserSettings().then(settings => {
this.setState({ useGravatar: settings.use_gravatar })
})
} }
onChangeAvatar = (event: ChangeEvent<HTMLInputElement>) => { onChangeAvatar = (event: ChangeEvent<HTMLInputElement>) => {
@@ -62,4 +58,8 @@ class General extends React.Component<Props, State> {
} }
} }
export default General; export default connect(
(state: StoreState) => ({
settings: state.userSettings
})
)(General);
+1 -1
View File
@@ -55,7 +55,7 @@ class Security extends React.Component<{}, State> {
placeholder={'Новый E-mail ещё раз'} placeholder={'Новый E-mail ещё раз'}
type={'email'} type={'email'}
value={email2} value={email2}
onChange={e => this.setState({ email1: e.target.value })} onChange={e => this.setState({ email2: e.target.value })}
/> />
<Button>Сохранить</Button> <Button>Сохранить</Button>
</form> </form>
+2 -1
View File
@@ -2,5 +2,6 @@ import {combineReducers} from "redux";
import currentUser from './currentUser' import currentUser from './currentUser'
import modal from "./modal"; import modal from "./modal";
import notifications from './notifications' import notifications from './notifications'
import userSettings from './userSettings';
export default combineReducers({ currentUser, modal, notifications }) export default combineReducers({ currentUser, modal, notifications, userSettings })
+19
View File
@@ -0,0 +1,19 @@
const SET_SETTINGS = 'unmei/userSettings/SET_SETTINGS';
const reducer = (state={}, action: Action<{settings: UserSettingsType}>) => {
switch (action.type) {
case SET_SETTINGS:
state = Object.assign({}, state, action.payload.settings);
return state;
default:
return state;
}
}
const setSettings = (settings: UserSettingsType) => ({
type: SET_SETTINGS,
payload: { settings }
});
export default reducer;
export { setSettings }
+7
View File
@@ -1,11 +1,18 @@
type StoreState = { type StoreState = {
currentUser: UserType currentUser: UserType
userSettings: UserSettingsType
notifications: React.ReactNode[] notifications: React.ReactNode[]
modal: React.ReactNode modal: React.ReactNode
} }
type Action<T> = {
type: string
payload: T
}
type SetUser = (user: UserType) => void type SetUser = (user: UserType) => void
type LogoutUser = () => void type LogoutUser = () => void
type SetSettings = (settings: UserSettingsType) => void
type SetModal = (modal: React.ReactNode | null) => void type SetModal = (modal: React.ReactNode | null) => void
type HideModal = () => void type HideModal = () => void
type AddNotification = (notification: React.ReactNode) => void type AddNotification = (notification: React.ReactNode) => void