diff --git a/src/components/user/User.js b/src/components/user/User.js
index 530e764..b3c5a0c 100644
--- a/src/components/user/User.js
+++ b/src/components/user/User.js
@@ -18,8 +18,8 @@ export class User extends Component {
constructor(props) {
super(props);
this.state = {
- submitSuccess: false,
- isNew: props.isNew
+ submitSuccess: props.fromCreation,
+ fromCreation: props.fromCreation
};
this.handleNameChange = this.handleNameChange.bind(this);
@@ -39,7 +39,8 @@ export class User extends Component {
...state,
name,
submitSuccess: false,
- nameValid: this.props.isValidUserName(name)
+ nameValid: this.props.isValidUserName(name),
+ nameError: null
}));
}
@@ -49,7 +50,8 @@ export class User extends Component {
...state,
email,
submitSuccess: false,
- emailValid: this.props.isValidUserEmail(email)
+ emailValid: this.props.isValidUserEmail(email),
+ emailError: null
}));
}
@@ -98,55 +100,12 @@ export class User extends Component {
return false;
}
- handleSubmit(event) {
- event.preventDefault();
- const { name, email, password, role } = this.state;
- this.setState(state => ({
- ...state,
- submitSuccess: false
- }));
-
- this.props
- .onSubmit(
- {
- name,
- email,
- password,
- role
- },
- this.props.user._id // Or this.state.newUserId (if new)
- )
- .then(() => {
- // TODO, receive here new user ID, set as "newUserId" in state
- this.setState(state => ({
- ...state,
- name: null,
- nameValid: false,
- email: null,
- emailValid: false,
- role: null,
- roleValid: null,
- passwordsValid: null,
- submitSuccess: true,
- isNew: false
- }));
- })
- .catch(() => {
- console.error("Error sending user");
- });
- }
-
- handleCancel() {
- event.preventDefault();
- this.props.onCancel();
- }
-
hasChangedName() {
return this.state.name && this.state.name.length;
}
hasValidName() {
- return this.props.isValidUserName(this.state.name);
+ return this.props.isValidUserName(this.state.name) && !this.state.nameError;
}
hasChangedEmail() {
@@ -154,7 +113,7 @@ export class User extends Component {
}
hasValidEmail() {
- return this.props.isValidUserEmail(this.state.email);
+ return this.props.isValidUserEmail(this.state.email) && !this.state.emailError;
}
hasChangedRole() {
@@ -170,7 +129,7 @@ export class User extends Component {
}
submitEnabled() {
- if (!this.state.isNew) {
+ if (!this.props.isNew) {
return (this.hasChangedPassword() || this.state.role) && !this.repeatedPasswordError();
}
return (
@@ -187,11 +146,21 @@ export class User extends Component {
}
handleNameBlur() {
- if (this.hasChangedName() && !this.hasValidName()) {
- this.setState(state => ({
- ...state,
- nameError: NAME_NOT_VALID
- }));
+ if (this.hasChangedName()) {
+ if (!this.hasValidName()) {
+ this.setState(state => ({
+ ...state,
+ nameError: NAME_NOT_VALID
+ }));
+ } else {
+ this.props.isUserNameRepeated(this.state.name).then(isRepeated => {
+ this.setState(state => ({
+ ...state,
+ nameValid: !isRepeated,
+ nameError: isRepeated ? "Name is repeated" : null
+ }));
+ });
+ }
} else {
this.setState(state => ({
...state,
@@ -201,11 +170,21 @@ export class User extends Component {
}
handleEmailBlur() {
- if (this.hasChangedEmail() && !this.hasValidEmail()) {
- this.setState(state => ({
- ...state,
- emailError: EMAIL_NOT_VALID
- }));
+ if (this.hasChangedEmail()) {
+ if (!this.hasValidEmail()) {
+ this.setState(state => ({
+ ...state,
+ emailError: EMAIL_NOT_VALID
+ }));
+ } else {
+ this.props.isUserEmailRepeated(this.state.email).then(isRepeated => {
+ this.setState(state => ({
+ ...state,
+ emailValid: !isRepeated,
+ emailError: isRepeated ? "Email is repeated" : null
+ }));
+ });
+ }
} else {
this.setState(state => ({
...state,
@@ -214,6 +193,50 @@ export class User extends Component {
}
}
+ handleSubmit(event) {
+ event.preventDefault();
+ const { name, email, password, role } = this.state;
+ this.setState(state => ({
+ ...state,
+ submitSuccess: false
+ }));
+
+ this.props
+ .onSubmit(
+ {
+ name,
+ email,
+ password,
+ role
+ },
+ this.props.user._id
+ )
+ .then(() => {
+ if (!this.props.isNew) {
+ this.setState(state => ({
+ ...state,
+ name: null,
+ nameValid: false,
+ email: null,
+ emailValid: false,
+ role: null,
+ roleValid: null,
+ passwordsValid: null,
+ submitSuccess: true,
+ fromCreation: false
+ }));
+ }
+ })
+ .catch(() => {
+ console.error("Error sending user");
+ });
+ }
+
+ handleCancel() {
+ event.preventDefault();
+ this.props.onCancel();
+ }
+
render() {
const {
user = {},
@@ -222,7 +245,8 @@ export class User extends Component {
roles,
currentUserIsAdmin,
submitLoading,
- submitError
+ submitError,
+ isNew
} = this.props;
const {
submitSuccess,
@@ -232,7 +256,7 @@ export class User extends Component {
emailValid,
roleValid,
passwordsValid,
- isNew
+ fromCreation
} = this.state;
const repeatedPasswordErrorMessage = passwordsValid ? (
@@ -344,8 +368,8 @@ export class User extends Component {
/>
{nameField}
{emailField}
@@ -380,7 +404,10 @@ export class User extends Component {
User.propTypes = {
currentUserIsAdmin: PropTypes.bool,
+ fromCreation: PropTypes.bool,
isNew: PropTypes.bool,
+ isUserEmailRepeated: PropTypes.func,
+ isUserNameRepeated: PropTypes.func,
isValidUserEmail: PropTypes.func,
isValidUserName: PropTypes.func,
onCancel: PropTypes.func,
diff --git a/src/data-sources/users/collection.js b/src/data-sources/users/collection.js
index 5331c00..bfa8dbe 100644
--- a/src/data-sources/users/collection.js
+++ b/src/data-sources/users/collection.js
@@ -43,6 +43,32 @@ export const usersCollectionWithExtraData = new Selector(
[]
);
+const exactSearchBy = (usersResults, { email, name }) => {
+ return usersResults.filter(user => {
+ let matchKeys = 0;
+ let matches = 0;
+ if (email) {
+ matchKeys++;
+ if (user.email === email) {
+ matches++;
+ }
+ }
+ if (name) {
+ matchKeys++;
+ if (user.name === name) {
+ matches++;
+ }
+ }
+ return matchKeys === matches;
+ });
+};
+
+export const usersCollectionExactFiltered = new Selector(
+ usersCollectionWithExtraData,
+ exactSearchBy,
+ []
+);
+
const searchBy = (usersResults, { search, showSystem }) => {
return usersResults.filter(user => {
if (!showSystem && user.isSystemRole) {
diff --git a/src/data-sources/users/index.js b/src/data-sources/users/index.js
index 1f2c6aa..b71a3a4 100644
--- a/src/data-sources/users/index.js
+++ b/src/data-sources/users/index.js
@@ -1,5 +1,9 @@
import { userMe, userMeWithAvatar, userMeIsAdmin } from "./me";
-import { usersCollection, usersCollectionFilteredAndSorted } from "./collection";
+import {
+ usersCollection,
+ usersCollectionExactFiltered,
+ usersCollectionFilteredAndSorted
+} from "./collection";
import {
usersModels,
usersModelsWithExtraData,
@@ -20,7 +24,7 @@ usersModels.onChangeAny(changeDetails => {
});
export { userMe, userMeWithAvatar, userMeIsAdmin };
-export { usersCollection, usersCollectionFilteredAndSorted };
+export { usersCollection, usersCollectionExactFiltered, usersCollectionFilteredAndSorted };
export {
usersModels,
usersModelsWithExtraData,
diff --git a/src/modules/users/Layouts.js b/src/modules/users/Layouts.js
index 85a0eb7..b17459a 100644
--- a/src/modules/users/Layouts.js
+++ b/src/modules/users/Layouts.js
@@ -1,6 +1,8 @@
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import PropTypes from "prop-types";
+import { plugins } from "reactive-data-source";
+import { pickBy, identity } from "lodash";
import { UsersContainer } from "./views/UsersContainer";
import { UsersList } from "./views/UsersList";
@@ -8,6 +10,7 @@ import { UsersList } from "./views/UsersList";
import { Component as UsersListTogglable } from "src/components/users-list-togglable";
import { UpdateUser } from "./views/UpdateUser";
import { CreateUser } from "./views/CreateUser";
+import { usersCollection, usersCollectionExactFiltered } from "src/data-sources/users";
// LIST USERS
@@ -67,15 +70,67 @@ export const UpdateUserLayout = withRouter(UpdateUserLayoutBase);
// CREATE USER
-export const CreateUserLayoutBase = ({ history }) => {
- const onCancel = () => {
- history.goBack();
- };
- return ;
-};
+export class CreateUserLayoutBase extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ newUserId: false
+ };
+ this.createUser = this.createUser.bind(this);
+ this.onCancel = this.onCancel.bind(this);
+ }
+
+ createUser(userData) {
+ return usersCollection.create(pickBy(userData, identity)).then(() => {
+ return usersCollectionExactFiltered
+ .filter({
+ name: userData.name
+ })
+ .read()
+ .then(results => {
+ this.setState(state => ({
+ ...state,
+ newUserId: results[0]._id
+ }));
+ });
+ });
+ }
+
+ onCancel() {
+ this.props.history.goBack();
+ }
+
+ render() {
+ const { newUserId } = this.state;
+
+ return newUserId ? (
+
+ ) : (
+
+ );
+ }
+}
CreateUserLayoutBase.propTypes = {
+ createError: PropTypes.instanceOf(Error),
+ createLoading: PropTypes.bool,
history: PropTypes.any
};
-export const CreateUserLayout = withRouter(CreateUserLayoutBase);
+export const mapDataSourceToProps = () => {
+ return {
+ createLoading: usersCollection.create.getters.loading,
+ createError: usersCollection.create.getters.error
+ };
+};
+
+export const CreateUserLayout = withRouter(
+ plugins.connect(mapDataSourceToProps)(CreateUserLayoutBase)
+);
diff --git a/src/modules/users/views/CreateUser.js b/src/modules/users/views/CreateUser.js
index f108a28..543f93c 100644
--- a/src/modules/users/views/CreateUser.js
+++ b/src/modules/users/views/CreateUser.js
@@ -1,29 +1,18 @@
-import { pickBy, identity } from "lodash";
-
import { plugins } from "reactive-data-source";
import { Component as UserComponent } from "src/components/user";
-import {
- usersCollection,
- userMeIsAdmin,
- isValidUserName,
- isValidUserEmail
-} from "src/data-sources/users";
+import { userMeIsAdmin, isValidUserName, isValidUserEmail } from "src/data-sources/users";
import { nonSystemRoles } from "src/data-sources/roles";
-const createUser = userData => usersCollection.create(pickBy(userData, identity));
+import { isUserNameRepeated, isUserEmailRepeated } from "./helpers";
export const mapDataSourceToProps = () => {
- const submitUser = usersCollection.create;
return {
currentUserIsAdmin: userMeIsAdmin.read.getters.value,
roles: nonSystemRoles.read.getters.value,
- onSubmit: createUser,
- submitLoading: submitUser.getters.loading,
- submitError: submitUser.getters.error,
- isNew: true,
- user: {},
+ isUserEmailRepeated,
+ isUserNameRepeated,
isValidUserName,
isValidUserEmail
};
diff --git a/src/modules/users/views/UpdateUser.js b/src/modules/users/views/UpdateUser.js
index e6433ea..3d093da 100644
--- a/src/modules/users/views/UpdateUser.js
+++ b/src/modules/users/views/UpdateUser.js
@@ -13,6 +13,8 @@ import {
isValidUserEmail
} from "src/data-sources/users";
+import { isUserNameRepeated, isUserEmailRepeated } from "./helpers";
+
const updateUser = (userData, id) => usersModels.byId(id).update(pickBy(userData, identity));
export const mapDataSourceToProps = ({ id }) => {
@@ -27,6 +29,8 @@ export const mapDataSourceToProps = ({ id }) => {
user: user.getters.value,
userLoading: user.getters.loading,
userError: user.getters.error,
+ isUserNameRepeated,
+ isUserEmailRepeated,
isValidUserName,
isValidUserEmail
};
diff --git a/src/modules/users/views/helpers.js b/src/modules/users/views/helpers.js
new file mode 100644
index 0000000..b54ad82
--- /dev/null
+++ b/src/modules/users/views/helpers.js
@@ -0,0 +1,23 @@
+import { usersCollectionExactFiltered } from "src/data-sources/users";
+
+export const isUserNameRepeated = name => {
+ console.log("VALIDATING!!");
+ return usersCollectionExactFiltered
+ .filter({
+ name
+ })
+ .read()
+ .then(results => {
+ console.log("RESULTS");
+ console.log(results);
+ return results.length > 0;
+ });
+};
+
+export const isUserEmailRepeated = email =>
+ usersCollectionExactFiltered
+ .filter({
+ email
+ })
+ .read()
+ .then(results => results.length > 0);