Skip to content

Commit

Permalink
Display an error message when trying to add an existing collaborator …
Browse files Browse the repository at this point in the history
…email

* Remove unused function `loadCollaboratorToEdit` from CollaboratorIndex
* Remove unused properties `confirmationText`, `onConfirm` from InviteModel
* Modify changeEmail action to accept a list of collaborators
* Modify changeEmail reducer to validate email isn't included between the collaborators
* Show error message resulting from the email validation
  • Loading branch information
ismaelbej committed Sep 4, 2024
1 parent b9c2a73 commit 0974c09
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 24 deletions.
3 changes: 2 additions & 1 deletion assets/js/actions/guest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ export const SET_CODE = "SET_CODE"
export const GENERATE_CODE = "GENERATE_CODE"
export const CLEAR = "CLEAR"

export const changeEmail = (email) => ({
export const changeEmail = (email, collaborators = []) => ({
type: CHANGE_EMAIL,
email,
collaborators,
})

export const changeLevel = (level) => ({
Expand Down
13 changes: 1 addition & 12 deletions assets/js/components/collaborators/CollaboratorIndex.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ class CollaboratorIndex extends Component {
$("#addCollaborator").modal("open")
}

loadCollaboratorToEdit(event, collaborator) {
event.preventDefault()
if (collaborator.invited) {
this.props.guestActions.changeEmail(collaborator.email)
this.props.guestActions.changeLevel(collaborator.role)
this.props.guestActions.setCode(collaborator.code)
$("#addCollaborator").modal("open")
}
}

levelChanged(e, collaborator) {
const { projectId, inviteActions, actions, t } = this.props
const level = e.target.value
Expand Down Expand Up @@ -143,9 +133,8 @@ class CollaboratorIndex extends Component {
modalId="addCollaborator"
modalText={t("The access of project collaborators will be managed through roles")}
header={t("Invite collaborators")}
confirmationText={t("Accept")}
onConfirm={(event) => event.preventDefault()}
style={{ maxWidth: "800px" }}
collaborators={collaborators}
/>
<div>
<CardTable title={title}>
Expand Down
33 changes: 25 additions & 8 deletions assets/js/components/collaborators/InviteModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class InviteModal extends Component {
}

emailOnChange(e) {
this.props.guestActions.changeEmail(e.target.value)
this.props.guestActions.changeEmail(e.target.value, this.props.collaborators)
}

emailOnBlur(e) {
Expand All @@ -42,7 +42,7 @@ export class InviteModal extends Component {
return
}
if (newEmail != config.user) {
Promise.resolve(this.props.guestActions.changeEmail(newEmail)).then(() => {
Promise.resolve(this.props.guestActions.changeEmail(newEmail, this.props.collaborators)).then(() => {
Promise.resolve(
this.props.actions.getInviteByEmailAndProject(projectId, guest.data.email)
).then((dbGuest) => {
Expand Down Expand Up @@ -97,10 +97,10 @@ export class InviteModal extends Component {
</a>
)

const validEmail = guest.data.email && !guest.errors.email
const emailError = this.getEmailError(guest);

const sendButton =
guest.data.code && validEmail ? (
guest.data.code && !emailError ? (
<a
href="#!"
className=" modal-action modal-close waves-effect btn-medium blue"
Expand Down Expand Up @@ -150,9 +150,9 @@ export class InviteModal extends Component {
}}
/>
</InputWithLabel>
{!validEmail ? (
{emailError ? (
<span className="small-text-bellow text-error">
{t("Please enter a valid email")}
{t(emailError)}
</span>
) : (
<span />
Expand Down Expand Up @@ -189,6 +189,23 @@ export class InviteModal extends Component {
</Modal>
)
}

getEmailError(guest) {
let errorCode = "invalid-email";
if (guest.data.email) {
errorCode = guest.errors.email
}

switch (errorCode) {
case null:
return null;
case "existing-email":
return "Email already in project";
case "invalid-email":
default:
return "Please enter a valid email";
}
}
}

InviteModal.propTypes = {
Expand All @@ -202,12 +219,11 @@ InviteModal.propTypes = {
linkText: PropTypes.string,
header: PropTypes.string.isRequired,
modalText: PropTypes.string.isRequired,
confirmationText: PropTypes.string.isRequired,
onConfirm: PropTypes.func.isRequired,
modalId: PropTypes.string.isRequired,
projectId: PropTypes.number,
style: PropTypes.object,
userLevel: PropTypes.string,
collaborators: PropTypes.array,
}

const mapDispatchToProps = (dispatch) => ({
Expand All @@ -220,6 +236,7 @@ const mapStateToProps = (state) => ({
projectId: state.project.data.id,
userLevel: state.project.data.level,
guest: state.guest,
collaborators: state.collaborators.items,
})

export default translate()(connect(mapStateToProps, mapDispatchToProps)(InviteModal))
14 changes: 12 additions & 2 deletions assets/js/reducers/guest.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,25 @@ const validEmail = (email) => {
}

const changeEmail = (state, action) => {
const { email, collaborators } = action;
let emailError = null;
if (!validEmail(email)) {
emailError = "invalid-email";
} else {
const collaborator = collaborators.find((c) => c.email === email);
if (collaborator) {
emailError = "existing-email";
}
}
return {
...state,
data: {
...state.data,
email: action.email,
},
errors: {
...state.errors,
email: !validEmail(action.email),
...state.errors,
email: emailError,
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/ask_web/controllers/invite_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ defmodule AskWeb.InviteControllerTest do
end

test "send invite to existing user", %{conn: conn, user: user} do
Process.register self(), :mail_target
Process.register(self(), :mail_target)
project = create_project_for_user(user)
code = "ABC1234"
level = "reader"
Expand Down

0 comments on commit 0974c09

Please sign in to comment.