#246: remove User class in favor of plain object in reducer

This commit is contained in:
SleepWalker 2017-01-12 08:12:56 +02:00
parent 85942d27ed
commit c5aa303793
3 changed files with 52 additions and 76 deletions

View File

@ -1,18 +1,17 @@
import { routeActions } from 'react-router-redux';
import authentication from 'services/api/authentication';
import accounts from 'services/api/accounts';
import { updateUser, setGuest } from 'components/user/actions';
import { setLocale } from 'components/i18n/actions';
import logger from 'services/logger';
/**
* @typedef {object} Account
* @property {string} account.id
* @property {string} account.username
* @property {string} account.email
* @property {string} account.token
* @property {string} account.refreshToken
* @property {string} id
* @property {string} username
* @property {string} email
* @property {string} token
* @property {string} refreshToken
*/
/**

View File

@ -1,66 +1,18 @@
import { PropTypes } from 'react';
const KEY_USER = 'user';
export default class User {
/**
* @param {object} [data] - plain object or jwt token or empty to load from storage
*
* @return {User}
*/
constructor(data) {
if (!data) {
return this.load();
}
// TODO: strict value types validation
const defaults = {
id: null,
uuid: null,
username: '',
email: '',
// will contain user's email or masked email
// (e.g. ex**ple@em*il.c**) depending on what information user have already provided
maskedEmail: '',
avatar: '',
lang: '',
isActive: false,
shouldAcceptRules: false, // whether user need to review updated rules
passwordChangedAt: null,
hasMojangUsernameCollision: false,
// frontend app specific attributes
isGuest: true,
goal: null, // the goal with wich user entered site
// TODO: remove me after migration to multy accs
token: '',
refreshToken: ''
};
const user = Object.keys(defaults).reduce((user, key) => {
if (data.hasOwnProperty(key)) {
user[key] = data[key];
}
return user;
}, defaults);
localStorage.setItem(KEY_USER, JSON.stringify(user));
return user;
}
load() {
try {
return new User(JSON.parse(localStorage.getItem(KEY_USER)));
} catch (error) {
return new User({isGuest: true});
}
}
}
/**
* @typedef {object} User
* @property {number} id
* @property {string} uuid
* @property {string} token
* @property {string} username
* @property {string} email
* @property {string} avatar
* @property {bool} isGuest
* @property {bool} isActive
* @property {number} passwordChangedAt - timestamp
* @property {bool} hasMojangUsernameCollision
*/
export const userShape = PropTypes.shape({
id: PropTypes.number,
uuid: PropTypes.string,

View File

@ -1,10 +1,28 @@
import { UPDATE, SET, CHANGE_LANG } from './actions';
import User from './User';
// TODO: возможно есть смысл инитить обьект User снаружи, так как редусер не должен столько знать
const defaults = {
id: null,
uuid: null,
username: '',
email: '',
// will contain user's email or masked email
// (e.g. ex**ple@em*il.c**) depending on what information user have already provided
maskedEmail: '',
avatar: '',
lang: '',
isActive: false,
shouldAcceptRules: false, // whether user need to review updated rules
passwordChangedAt: null,
hasMojangUsernameCollision: false,
// frontend specific attributes
isGuest: true,
goal: null // the goal with wich user entered site
};
export default function user(
state = new User(),
state = null,
{type, payload = null}
) {
switch (type) {
@ -13,25 +31,32 @@ export default function user(
throw new Error('payload.lang is required for user reducer');
}
return new User({
return {
...state,
lang: payload.lang
});
};
case UPDATE:
if (!payload) {
throw new Error('payload is required for user reducer');
}
return new User({
return {
...state,
...payload
});
};
case SET:
return new User(payload || {});
payload = payload || {};
return {
...defaults,
...payload
};
default:
return state;
return state || {
...defaults
};
}
}