From a277b638a4e42ef1f8b8f8eaa3080c49817696b0 Mon Sep 17 00:00:00 2001 From: Javier Brea Date: Tue, 12 Feb 2019 20:25:24 +0100 Subject: [PATCH] Add account section --- src/app/routes.js | 3 +- src/components/user/User.js | 17 ++++----- src/data-sources/users/index.js | 25 ++++++++----- src/data-sources/users/me.js | 12 ++++--- src/data-sources/users/model.js | 8 ----- src/data-sources/users/validations.js | 25 +++++++++++++ src/modules/account/Layouts.js | 15 ++++++++ src/modules/account/index.js | 3 ++ src/modules/account/views/UpdateUser.js | 44 +++++++++++++++++++++++ src/modules/account/views/UpdateUserMe.js | 21 +++++++++++ src/modules/menu-user/views/UserMenu.js | 8 ++--- src/modules/users/Layouts.js | 4 +-- src/modules/users/views/CreateUser.js | 6 ++-- src/modules/users/views/UpdateUser.js | 6 ++-- src/modules/users/views/helpers.js | 17 --------- 15 files changed, 153 insertions(+), 61 deletions(-) create mode 100644 src/data-sources/users/validations.js create mode 100644 src/modules/account/Layouts.js create mode 100644 src/modules/account/index.js create mode 100644 src/modules/account/views/UpdateUser.js create mode 100644 src/modules/account/views/UpdateUserMe.js delete mode 100644 src/modules/users/views/helpers.js diff --git a/src/app/routes.js b/src/app/routes.js index 3005faf..0290b51 100644 --- a/src/app/routes.js +++ b/src/app/routes.js @@ -6,6 +6,7 @@ import { Module as Plugins } from "src/modules/plugins"; import { Module as Login } from "src/modules/login"; import { Module as Activity } from "src/modules/activity"; import { Module as Users } from "src/modules/users"; +import { Module as Account } from "src/modules/account"; import { environment } from "./config/environment"; @@ -49,7 +50,7 @@ export const sections = { account: { name: "Account", route: "/account", - component: null, + component: Account, showInMenu: false }, abilities: { diff --git a/src/components/user/User.js b/src/components/user/User.js index e7edd0b..2783df6 100644 --- a/src/components/user/User.js +++ b/src/components/user/User.js @@ -208,15 +208,12 @@ export class User extends Component { })); this.props - .onSubmit( - { - name, - email, - password, - role - }, - this.props.user._id - ) + .onSubmit({ + name, + email, + password, + role + }) .then(() => { if (!this.props.isNew) { this.setState(state => ({ @@ -260,7 +257,7 @@ export class User extends Component { handleDeleteConfirm() { event.preventDefault(); - this.props.onDelete(this.props.user._id); + this.props.onDelete(); } render() { diff --git a/src/data-sources/users/index.js b/src/data-sources/users/index.js index b71a3a4..1c534be 100644 --- a/src/data-sources/users/index.js +++ b/src/data-sources/users/index.js @@ -1,16 +1,17 @@ -import { userMe, userMeWithAvatar, userMeIsAdmin } from "./me"; +import { userMe, userMeWithExtraData, userMeIsAdmin } from "./me"; import { usersCollection, usersCollectionExactFiltered, usersCollectionFilteredAndSorted } from "./collection"; +import { usersModels, usersModelsWithExtraData, userAllowedRoles } from "./model"; + import { - usersModels, - usersModelsWithExtraData, - userAllowedRoles, isValidUserName, - isValidUserEmail -} from "./model"; + isValidUserEmail, + isUserNameRepeated, + isUserEmailRepeated +} from "./validations"; usersModels.onChangeAny(changeDetails => { if ( @@ -23,12 +24,18 @@ usersModels.onChangeAny(changeDetails => { } }); -export { userMe, userMeWithAvatar, userMeIsAdmin }; -export { usersCollection, usersCollectionExactFiltered, usersCollectionFilteredAndSorted }; export { + userMe, + userMeWithExtraData, + userMeIsAdmin, + usersCollection, + usersCollectionExactFiltered, + usersCollectionFilteredAndSorted, usersModels, usersModelsWithExtraData, userAllowedRoles, isValidUserName, - isValidUserEmail + isValidUserEmail, + isUserNameRepeated, + isUserEmailRepeated }; diff --git a/src/data-sources/users/me.js b/src/data-sources/users/me.js index fbec0ad..2faf8d7 100644 --- a/src/data-sources/users/me.js +++ b/src/data-sources/users/me.js @@ -1,7 +1,9 @@ import { origins, Selector } from "reactive-data-source"; +import { roles } from "../roles"; + import { userAvatar, byEmailFilter } from "./avatar"; -import { avatarValueFromResponse } from "./helpers"; +import { isSystemRole, avatarValueFromResponse } from "./helpers"; export const userMe = new origins.Api( "/users/me", @@ -11,15 +13,17 @@ export const userMe = new origins.Api( } ); -export const userMeWithAvatar = new Selector( +export const userMeWithExtraData = new Selector( userMe, { source: userAvatar, filter: (filter, results) => byEmailFilter(results[0].email) }, - (userMeData, userMeAvatarResponse) => ({ + roles, + (userMeData, userMeAvatarResponse, rolesResults) => ({ ...userMeData, - avatar: avatarValueFromResponse(userMeAvatarResponse) + avatar: avatarValueFromResponse(userMeAvatarResponse), + isSystemRole: isSystemRole(userMeData, rolesResults) }), {} ); diff --git a/src/data-sources/users/model.js b/src/data-sources/users/model.js index e9649d2..61d35d5 100644 --- a/src/data-sources/users/model.js +++ b/src/data-sources/users/model.js @@ -6,14 +6,6 @@ import { byIdFilter } from "../helpers"; import { isSystemRole, avatarValueFromResponse } from "./helpers"; import { userAvatar, byEmailFilter } from "./avatar"; -const NAME_REGEX = /^[a-z0-9_.-]*$/; - -const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$/; - -export const isValidUserName = name => name.length > 4 && NAME_REGEX.test(name); - -export const isValidUserEmail = email => EMAIL_REGEX.test(email); - export const usersModels = new origins.Api( "/users/:id", { diff --git a/src/data-sources/users/validations.js b/src/data-sources/users/validations.js new file mode 100644 index 0000000..d353be6 --- /dev/null +++ b/src/data-sources/users/validations.js @@ -0,0 +1,25 @@ +import { usersCollectionExactFiltered } from "./collection"; + +const NAME_REGEX = /^[a-z0-9_.-]*$/; + +const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$/; + +export const isValidUserName = name => name.length > 4 && NAME_REGEX.test(name); + +export const isValidUserEmail = email => EMAIL_REGEX.test(email); + +export const isUserNameRepeated = name => + usersCollectionExactFiltered + .filter({ + name + }) + .read() + .then(results => results.length > 0); + +export const isUserEmailRepeated = email => + usersCollectionExactFiltered + .filter({ + email + }) + .read() + .then(results => results.length > 0); diff --git a/src/modules/account/Layouts.js b/src/modules/account/Layouts.js new file mode 100644 index 0000000..50b41ec --- /dev/null +++ b/src/modules/account/Layouts.js @@ -0,0 +1,15 @@ +import React from "react"; +import { withRouter } from "react-router-dom"; +import PropTypes from "prop-types"; + +import { UpdateUserMe } from "./views/UpdateUserMe"; + +// UPDATE USER + +export const AccountBase = ({ history }) => history.goBack()} />; + +AccountBase.propTypes = { + history: PropTypes.any +}; + +export const Account = withRouter(AccountBase); diff --git a/src/modules/account/index.js b/src/modules/account/index.js new file mode 100644 index 0000000..c798acc --- /dev/null +++ b/src/modules/account/index.js @@ -0,0 +1,3 @@ +import { Account } from "./Layouts"; + +export const Module = Account; diff --git a/src/modules/account/views/UpdateUser.js b/src/modules/account/views/UpdateUser.js new file mode 100644 index 0000000..b99609d --- /dev/null +++ b/src/modules/account/views/UpdateUser.js @@ -0,0 +1,44 @@ +import { pickBy, identity } from "lodash"; + +import { plugins } from "reactive-data-source"; + +import { Component as UserComponent } from "src/components/user"; + +import { + usersModels, + usersModelsWithExtraData, + userAllowedRoles, + userMeIsAdmin, + isValidUserName, + isValidUserEmail, + isUserNameRepeated, + isUserEmailRepeated +} from "src/data-sources/users"; + +export const mapDataSourceToProps = ({ id }) => { + const readUser = usersModelsWithExtraData.byId(id).read; + const user = usersModels.byId(id); + const updateUser = user.update; + const deleteUser = user.delete; + + const submitUpdateUser = userData => updateUser(pickBy(userData, identity)); + + return { + currentUserIsAdmin: userMeIsAdmin.read.getters.value, + roles: userAllowedRoles.byId(id).read.getters.value, + onSubmit: submitUpdateUser, + submitLoading: updateUser.getters.loading, + submitError: updateUser.getters.error, + user: readUser.getters.value, + userLoading: readUser.getters.loading, + userError: readUser.getters.error, + userDeleteLoading: deleteUser.getters.loading, + userDeleteError: deleteUser.getters.error, + isUserNameRepeated, + isUserEmailRepeated, + isValidUserName, + isValidUserEmail + }; +}; + +export const UpdateUser = plugins.connect(mapDataSourceToProps)(UserComponent); diff --git a/src/modules/account/views/UpdateUserMe.js b/src/modules/account/views/UpdateUserMe.js new file mode 100644 index 0000000..54c3ebe --- /dev/null +++ b/src/modules/account/views/UpdateUserMe.js @@ -0,0 +1,21 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { plugins } from "reactive-data-source"; + +import { UpdateUser } from "./UpdateUser"; + +import { userMe } from "src/data-sources/users"; + +export const UpdateUserMeComponent = ({ user, goBack }) => + user._id ? : null; + +UpdateUserMeComponent.propTypes = { + goBack: PropTypes.func, + user: PropTypes.any +}; + +export const mapDataSourceToProps = () => ({ + user: userMe.read.getters.value +}); + +export const UpdateUserMe = plugins.connect(mapDataSourceToProps)(UpdateUserMeComponent); diff --git a/src/modules/menu-user/views/UserMenu.js b/src/modules/menu-user/views/UserMenu.js index ab36560..5293aa0 100644 --- a/src/modules/menu-user/views/UserMenu.js +++ b/src/modules/menu-user/views/UserMenu.js @@ -4,7 +4,7 @@ import { Component as UserMenuComponent } from "src/components/menu-user"; import { authSession } from "src/data-sources/authentication"; import { logout, cleanAll } from "src/data-sources/setup"; -import { userMeWithAvatar } from "src/data-sources/users"; +import { userMeWithExtraData } from "src/data-sources/users"; const doLogout = event => { event.preventDefault(); @@ -15,9 +15,9 @@ const doLogout = event => { export const mapDataSourceToProps = () => { return { doLogout, - loading: userMeWithAvatar.read.getters.loading, - error: userMeWithAvatar.read.getters.error, - user: userMeWithAvatar.read.getters.value + loading: userMeWithExtraData.read.getters.loading, + error: userMeWithExtraData.read.getters.error, + user: userMeWithExtraData.read.getters.value }; }; diff --git a/src/modules/users/Layouts.js b/src/modules/users/Layouts.js index 45e02fe..4a604cd 100644 --- a/src/modules/users/Layouts.js +++ b/src/modules/users/Layouts.js @@ -33,7 +33,7 @@ export const UsersLayout = withRouter(UsersLayoutBase); // UPDATE USER export const UpdateUserLayoutBase = ({ match, history }) => ( - history.goBack()} /> + history.goBack()} /> ); UpdateUserLayoutBase.propTypes = { @@ -46,7 +46,7 @@ export const UpdateUserLayout = withRouter(UpdateUserLayoutBase); // CREATE USER export const CreateUserLayoutBase = ({ history }) => ( - history.goBack()} /> + history.goBack()} /> ); CreateUserLayoutBase.propTypes = { diff --git a/src/modules/users/views/CreateUser.js b/src/modules/users/views/CreateUser.js index 0d1d42c..a30aca4 100644 --- a/src/modules/users/views/CreateUser.js +++ b/src/modules/users/views/CreateUser.js @@ -6,12 +6,12 @@ import { usersCollection, userMeIsAdmin, isValidUserName, - isValidUserEmail + isValidUserEmail, + isUserNameRepeated, + isUserEmailRepeated } from "src/data-sources/users"; import { nonSystemRoles } from "src/data-sources/roles"; -import { isUserNameRepeated, isUserEmailRepeated } from "./helpers"; - export const mapDataSourceToProps = () => { return { currentUserIsAdmin: userMeIsAdmin.read.getters.value, diff --git a/src/modules/users/views/UpdateUser.js b/src/modules/users/views/UpdateUser.js index f4984dc..b99609d 100644 --- a/src/modules/users/views/UpdateUser.js +++ b/src/modules/users/views/UpdateUser.js @@ -10,11 +10,11 @@ import { userAllowedRoles, userMeIsAdmin, isValidUserName, - isValidUserEmail + isValidUserEmail, + isUserNameRepeated, + isUserEmailRepeated } from "src/data-sources/users"; -import { isUserNameRepeated, isUserEmailRepeated } from "./helpers"; - export const mapDataSourceToProps = ({ id }) => { const readUser = usersModelsWithExtraData.byId(id).read; const user = usersModels.byId(id); diff --git a/src/modules/users/views/helpers.js b/src/modules/users/views/helpers.js deleted file mode 100644 index ec3debe..0000000 --- a/src/modules/users/views/helpers.js +++ /dev/null @@ -1,17 +0,0 @@ -import { usersCollectionExactFiltered } from "src/data-sources/users"; - -export const isUserNameRepeated = name => - usersCollectionExactFiltered - .filter({ - name - }) - .read() - .then(results => results.length > 0); - -export const isUserEmailRepeated = email => - usersCollectionExactFiltered - .filter({ - email - }) - .read() - .then(results => results.length > 0);