diff --git a/package.json b/package.json
index 484da52..1681f7b 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"dependencies": {
"babel-polyfill": "^6.26.0",
"bulma": "^0.6.2",
+ "bulma-checkradio": "^1.0.1",
"dexie": "^2.0.1",
"font-awesome": "^4.7.0",
"inferno": "^4.0.4",
diff --git a/public/api/User.php b/public/api/User.php
index fbcded5..0e935e0 100644
--- a/public/api/User.php
+++ b/public/api/User.php
@@ -24,7 +24,10 @@ class User {
}
} else if (password_verify($password, $user['password'])) {
$this->db->execute('UPDATE users SET last_login=' . time() . ' WHERE id=' . $user['id']);
- return $this->generateUserToken($user['id'], $user['current_dictionary']);
+ return array(
+ 'token' => $this->generateUserToken($user['id'], $user['current_dictionary']),
+ 'user' => $this->getUserData($user['id']),
+ );
}
}
return false;
@@ -60,13 +63,57 @@ VALUES (?, ?, ?, ?, ?, '. time() .')';
$new_dictionary = $this->dictionary->create($new_user_id);
if ($new_dictionary !== false) {
- return $this->generateUserToken($new_user_id, $new_dictionary);
+ return array(
+ 'token' => $this->generateUserToken($new_user_id, $new_dictionary),
+ 'user' => $this->getUserData($new_user_id),
+ );
}
}
return false;
}
+ public function setUserData ($token, $user_data) {
+ $token_data = $this->token->decode($token);
+ if ($token_data !== false) {
+ $query = 'UPDATE users SET email=?, public_name=?, username=?, allow_email=?, use_ipa=? WHERE id=?';
+ $properties = array(
+ $user_data['email'],
+ $user_data['publicName'],
+ $user_data['username'],
+ $user_data['allowEmail'],
+ $user_data['useIPAPronunciation'],
+ $user_id,
+ );
+ $update_success = $this->db->execute($query, $properties);
+ if ($update_success) {
+ return array(
+ 'token' => $token,
+ 'userData' => $user_data,
+ );
+ }
+ }
+
+ return false;
+ }
+
+ public function getUserData ($user_id) {
+ $query = 'SELECT * FROM users WHERE id=?';
+ $stmt = $this->db->query($query, array($user_id));
+ $user = $stmt->fetch();
+ if ($stmt && $user) {
+ return array(
+ 'email' => $user['email'],
+ 'username' => $user['username'],
+ 'publicName' => $user['public_name'],
+ 'allowEmails' => $user['allow_email'] == 1 ? true : false,
+ 'useIPAPronunciation' => $user['use_ipa'] == 1 ? true : false,
+ );
+ }
+
+ return false;
+ }
+
public function createNewDictionary ($token) {
$user_data = $this->token->decode($token);
if ($user_data !== false) {
diff --git a/public/api/index.php b/public/api/index.php
index 79b6e04..e684dca 100644
--- a/public/api/index.php
+++ b/public/api/index.php
@@ -12,10 +12,10 @@ switch ($action) {
case 'login': {
if (isset($request['email']) && isset($request['password'])) {
$user = new User();
- $token = $user->logIn($request['email'], $request['password']);
- if ($token !== false) {
+ $user_data = $user->logIn($request['email'], $request['password']);
+ if ($user_data !== false) {
return Response::json(array(
- 'data' => $token,
+ 'data' => $user_data,
'error' => false,
), 200);
}
@@ -33,10 +33,10 @@ switch ($action) {
if (isset($request['email']) && isset($request['password'])) {
$user = new User();
if (!$user->emailExists($request['email'])) {
- $token = $user->create($request['email'], $request['password'], $request['userData']);
- if ($token !== false) {
+ $user_data = $user->create($request['email'], $request['password'], $request['userData']);
+ if ($user_data !== false) {
return Response::json(array(
- 'data' => $token,
+ 'data' => $user_data,
'error' => false,
), 201);
}
@@ -103,6 +103,26 @@ switch ($action) {
'error' => true,
), 403);
}
+ case 'set-user-data': {
+ if ($token !== false && isset($request['userData'])) {
+ $user = new User();
+ $updated_user = $user->setUserData($token, $request['userData']);
+ if ($updated_user !== false) {
+ return Response::json(array(
+ 'data' => $updated_user,
+ 'error' => false,
+ ), 200);
+ }
+ return Response::json(array(
+ 'data' => 'Could not set user data: missing data',
+ 'error' => true,
+ ), 400);
+ }
+ return Response::json(array(
+ 'data' => 'Could not get dictionaries: no token provided',
+ 'error' => true,
+ ), 403);
+ }
case 'create-new-dictionary': {
if ($token !== false) {
$user = new User();
diff --git a/src/components/MainDisplay.jsx b/src/components/MainDisplay.jsx
index 51cae62..28bca00 100644
--- a/src/components/MainDisplay.jsx
+++ b/src/components/MainDisplay.jsx
@@ -16,8 +16,10 @@ export class MainDisplay extends Component {
PropTypes.checkPropTypes({
dictionaryInfo: PropTypes.object.isRequired,
+ isLoadingWords: PropTypes.bool,
wordsToDisplay: PropTypes.array.isRequired,
wordsAreFiltered: PropTypes.bool,
+ wordsInCurrentList: PropTypes.number,
currentPage: PropTypes.number,
itemsPerPage: PropTypes.number,
stats: PropTypes.object.isRequired,
@@ -55,8 +57,10 @@ export class MainDisplay extends Component {
render () {
const {
dictionaryInfo,
+ isLoadingWords,
wordsToDisplay,
wordsAreFiltered,
+ wordsInCurrentList,
currentPage,
itemsPerPage,
stats,
@@ -105,7 +109,16 @@ export class MainDisplay extends Component {
)}
+
+
@@ -114,7 +127,8 @@ export class MainDisplay extends Component {
currentPage={currentPage}
itemsPerPage={itemsPerPage}
stats={stats}
- setPage={ setPage } />
+ setPage={setPage}
+ wordsInCurrentList={wordsInCurrentList} />
diff --git a/src/components/display/WordsList.jsx b/src/components/display/WordsList.jsx
index 98bfa6e..058b4ad 100644
--- a/src/components/display/WordsList.jsx
+++ b/src/components/display/WordsList.jsx
@@ -13,6 +13,7 @@ export class WordsList extends Component {
super(props);
PropTypes.checkPropTypes({
+ isLoadingWords: PropTypes.bool,
adsEveryXWords: PropTypes.number,
words: PropTypes.array,
updateDisplay: PropTypes.func.isRequired,
@@ -22,6 +23,12 @@ export class WordsList extends Component {
render () {
const adsEveryXWords = this.props.adsEveryXWords || 10;
+ if (this.props.isLoadingWords) {
+ return
;
+ }
+
return (
diff --git a/src/components/management/AccountManager/MyAccount.jsx b/src/components/management/AccountManager/MyAccount.jsx
new file mode 100644
index 0000000..085abe6
--- /dev/null
+++ b/src/components/management/AccountManager/MyAccount.jsx
@@ -0,0 +1,94 @@
+import Inferno from 'inferno';
+import { Component } from 'inferno';
+import PropTypes from 'prop-types';
+
+export class MyAccount extends Component {
+ constructor(props) {
+ super(props);
+
+ PropTypes.checkPropTypes({
+ email: PropTypes.string.isRequired,
+ username: PropTypes.string.isRequired,
+ publicName: PropTypes.string.isRequired,
+ allowEmails: PropTypes.bool.isRequired,
+ useIPAPronunciation: PropTypes.bool.isRequired,
+ userDictionaries: PropTypes.array.isRequired,
+ updateUserData: PropTypes.func,
+ changeDictionary: PropTypes.func,
+ }, props, 'prop', 'LoginForm');
+
+ this.state = {
+ email: this.props.email,
+ username: this.props.username,
+ publicName: this.props.publicName,
+ allowEmails: this.props.allowEmails,
+ useIPAPronunciation: this.props.useIPAPronunciation,
+ userDictionaries: this.props.userDictionaries,
+ };
+ }
+
+ render() {
+ return (
+
+
+
+
+
Account Details
+
+ Email: {this.state.email}
+
+
+ Username: {this.state.username}
+
+
+
+
+ {this.setState({publicName: event.target.value})}} />
+
+
+
+
+ { this.setState({ allowEmails: !this.state.allowEmails }) }} />
+
+
+
+
+ { this.setState({ useIPAPronunciation: !this.state.useIPAPronunciation }) }} />
+
+
+
+
+
+
Account Actions
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/components/management/AccountManager/index.jsx b/src/components/management/AccountManager/index.jsx
index d76d864..c01f855 100644
--- a/src/components/management/AccountManager/index.jsx
+++ b/src/components/management/AccountManager/index.jsx
@@ -6,9 +6,18 @@ import store from 'store';
import { Modal } from '../../structure/Modal';
import { LoginForm } from './LoginForm';
+import { MyAccount } from './MyAccount';
import { request } from '../../../Helpers';
+const defaultUserData = {
+ email: '',
+ username: '',
+ publicName: '',
+ allowEmails: true,
+ useIPAPronunciation: true,
+};
+
export class AccountManager extends Component {
constructor (props) {
super(props);
@@ -17,9 +26,21 @@ export class AccountManager extends Component {
updater: PropTypes.object.isRequired,
}, props, 'prop', 'AccountManager');
+ const userData = store.get('LexicongaUserData');
+
this.state = {
isLoggedIn: false,
+ userData: {
+ email: userData ? userData.email : defaultUserData.email,
+ username: userData ? userData.username : defaultUserData.username,
+ publicName: userData ? userData.publicName : defaultUserData.publicName,
+ allowEmails: userData ? userData.allowEmails : defaultUserData.allowEmails,
+ useIPAPronunciation: userData ? userData.useIPAPronunciation : defaultUserData.useIPAPronunciation,
+ },
+ userDictionaries: [],
};
+
+ this.getDictionaryNames();
}
logIn (email, password) {
@@ -28,7 +49,12 @@ export class AccountManager extends Component {
logOut () {
store.remove('LexicongaToken');
- this.setState({ isLoggedIn: false });
+ store.remove('LexicongaUserData');
+ this.setState({
+ isLoggedIn: false,
+ userData: Object.assign({}, defaultUserData),
+ userDictionaries: [],
+ });
}
signUp (email, password, userData) {
@@ -44,23 +70,69 @@ export class AccountManager extends Component {
if (error) {
console.error(data);
} else {
- store.set('LexicongaToken', data);
- this.setState({ isLoggedIn: true }, () => {
+ store.set('LexicongaToken', data.token);
+ store.set('LexicongaUserData', data.user);
+ this.setState({
+ isLoggedIn: true,
+ userData: data.user,
+ }, () => {
+ this.getDictionaryNames();
this.props.updater.sync();
});
}
}
+ updateUserData (newUserData) {
+ const token = store.get('LexicongaToken');
+
+ if (token) {
+ store.set('LexicongaUserData', newUserData);
+ this.setState({ userData: newUserData }, () => {
+ request('set-user-data', { token, userData: newUserData }, (response) => {
+ const {data, error} = response;
+ if (error) {
+ console.error(data);
+ } else {
+ console.log(data);
+ }
+ })
+ });
+ }
+ }
+
+ getDictionaryNames () {
+ const token = store.get('LexicongaToken');
+
+ if (token) {
+ return request('get-all-dictionary-names', { token }, (response) => {
+ const {data, error} = response;
+ if (error) {
+ console.error(data);
+ } else {
+ this.setState({ userDictionaries: data });
+ }
+ });
+ }
+ }
+
render () {
const token = store.get('LexicongaToken');
if (token) {
+ const { userData } = this.state;
+
return (
-
-
+
+ {} } />
Log Out
diff --git a/src/components/management/EditDictionaryModal/EditSettingsForm.jsx b/src/components/management/EditDictionaryModal/EditSettingsForm.jsx
index f79f53c..12b3ddd 100644
--- a/src/components/management/EditDictionaryModal/EditSettingsForm.jsx
+++ b/src/components/management/EditDictionaryModal/EditSettingsForm.jsx
@@ -30,17 +30,16 @@ export const EditSettingsForm = (props) => {
-