account identity update
allow users to update their JamKazam email and password securly.
This commit is contained in:
parent
b563f22a32
commit
aeb2e50692
|
|
@ -3,7 +3,8 @@ import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const JKModalDialog = ({ title, children, show, onToggle, showFooter }) => {
|
||||
const JKModalDialog = (args) => {
|
||||
const { show, title, children, onToggle, showFooter, ...rest } = args;
|
||||
const [modal, setModal] = useState(show);
|
||||
|
||||
const toggle = () => {
|
||||
|
|
@ -18,7 +19,7 @@ const JKModalDialog = ({ title, children, show, onToggle, showFooter }) => {
|
|||
}, [show]);
|
||||
|
||||
return (
|
||||
<Modal isOpen={modal} toggle={toggle}>
|
||||
<Modal isOpen={modal} toggle={toggle} {...rest}>
|
||||
<ModalHeader toggle={toggle}>{title}</ModalHeader>
|
||||
<ModalBody>{children}</ModalBody>
|
||||
{showFooter && (
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import JKNewMusicSession from '../page/JKNewMusicSession';
|
|||
import JKMusicSessionsLobby from '../page/JKMusicSessionsLobby';
|
||||
|
||||
import JKEditProfile from '../page/JKEditProfile';
|
||||
import JKEditAccount from '../page/JKEditAccount';
|
||||
|
||||
//import loadable from '@loadable/component';
|
||||
//const DashboardRoutes = loadable(() => import('../../layouts/JKDashboardRoutes'));
|
||||
|
|
@ -198,6 +199,7 @@ function JKDashboardMain() {
|
|||
<PrivateRoute path="/sessions" component={JKMusicSessions} />
|
||||
<PrivateRoute path="/notifications" component={JKNotifications} />
|
||||
<PrivateRoute path="/profile" component={JKEditProfile} />
|
||||
<PrivateRoute path="/account/identity" component={JKEditAccount} />
|
||||
{/*Redirect*/}
|
||||
<Redirect to="/errors/404" />
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Row, Col, Card, CardBody } from 'reactstrap';
|
||||
import FalconCardHeader from '../common/FalconCardHeader';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import JKEditEmail from '../profile/JKEditEmail';
|
||||
import JKEditPassword from '../profile/JKEditPassword';
|
||||
import JKModalDialog from '../common/JKModalDialog';
|
||||
|
||||
const JKEditAccount = () => {
|
||||
const { t } = useTranslation('account');
|
||||
const [alertText, setAlertText] = useState("")
|
||||
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const toggleAlert = () => setShowAlert(!showAlert);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<FalconCardHeader title={t('identity.page_title')} titleClass="font-weight-bold" />
|
||||
<CardBody className="pt-3" style={{ backgroundColor: '#edf2f9' }}>
|
||||
<Row>
|
||||
<Col>
|
||||
<JKEditEmail setAlert={setAlertText} toggleAlert={toggleAlert} />
|
||||
</Col>
|
||||
<Col>
|
||||
<JKEditPassword setAlert={setAlertText} toggleAlert={toggleAlert} />
|
||||
</Col>
|
||||
<Col></Col>
|
||||
</Row>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<JKModalDialog
|
||||
show={showAlert}
|
||||
onToggle={toggleAlert}
|
||||
title={t('identity.modals.update_notification.title')}
|
||||
data-testid="native-app-unavailable"
|
||||
size="md"
|
||||
>
|
||||
{alertText}
|
||||
</JKModalDialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKEditAccount;
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
|
||||
Card,
|
||||
CardHeader,
|
||||
CardBody,
|
||||
Form,
|
||||
FormGroup,
|
||||
Label,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputGroupAddon
|
||||
} from 'reactstrap';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuth } from '../../context/UserAuth';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { postUpdateAccountEmail } from '../../helpers/rest';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
const JKEditEmail = ({setAlert, toggleAlert}) => {
|
||||
const { t } = useTranslation('account');
|
||||
const { currentUser } = useAuth();
|
||||
const [user, setUser] = useState(null);
|
||||
const [showEmailPassword, setShowEmailPassword] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { errors },
|
||||
setError,
|
||||
setValue,
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
current_password: '',
|
||||
new_email: ''
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
setUser(currentUser);
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
const onSubmitEmail = (data) => {
|
||||
setSubmitting(true)
|
||||
//post
|
||||
const { new_email, current_password } = data;
|
||||
postUpdateAccountEmail(currentUser.id, { email: new_email, current_password })
|
||||
.then(response => {
|
||||
setAlert('A confirmation email has been sent to your email. Please check your email and click the link to confirm your new email address.');
|
||||
setValue('current_password', '');
|
||||
setValue('new_email', '');
|
||||
toggleAlert()
|
||||
})
|
||||
.catch(async error => {
|
||||
const errorResp = await error.json()
|
||||
console.log(errorResp)
|
||||
if(errorResp.errors){
|
||||
const errors = errorResp.errors;
|
||||
if(errors.current_password && errors.current_password.length){
|
||||
errors.current_password.forEach(error => {
|
||||
setError('current_password', {
|
||||
type: 'manual',
|
||||
message: `Current password ${error}`
|
||||
})
|
||||
})
|
||||
}
|
||||
if(errors.update_email && errors.update_email.length){
|
||||
errors.update_email.forEach(error => {
|
||||
setError('new_email', {
|
||||
type: 'manual',
|
||||
message: `New email ${error}`
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}).finally(() => {
|
||||
setSubmitting(false)
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h5>Email</h5>
|
||||
</CardHeader>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300 }}>
|
||||
<small>
|
||||
To update the email associated with your account, enter your current password (for security reasons) and the
|
||||
new email, and click the "Save Email" button.
|
||||
</small>
|
||||
|
||||
<Form className="mt-2" onSubmit={handleSubmit(onSubmitEmail)}>
|
||||
<FormGroup>
|
||||
<Label for="current_password">Current Password</Label>
|
||||
<Controller
|
||||
name="current_password"
|
||||
control={control}
|
||||
rules={{ required: 'Current password is required' }}
|
||||
render={({ field }) => (
|
||||
<InputGroup>
|
||||
<Input
|
||||
{...field}
|
||||
type={showEmailPassword ? 'text' : 'password'}
|
||||
className="form-control"
|
||||
id="current_password"
|
||||
placeholder="Current Password"
|
||||
/>
|
||||
<InputGroupAddon
|
||||
addonType="append"
|
||||
onClick={() => {
|
||||
setShowEmailPassword(!showEmailPassword);
|
||||
}}
|
||||
>
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={showEmailPassword ? 'eye-slash' : 'eye'} />
|
||||
</span>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
)}
|
||||
/>
|
||||
{errors.current_password && <div className="text-danger"><small>{errors.current_password.message}</small></div>}
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Label for="new_email">New Email</Label>
|
||||
<Controller
|
||||
name="new_email"
|
||||
control={control}
|
||||
rules={{
|
||||
required: 'New email is required',
|
||||
pattern: {
|
||||
value: /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/,
|
||||
message: 'Invalid email address'
|
||||
}
|
||||
}}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
{...field}
|
||||
type="email"
|
||||
className="form-control"
|
||||
id="new_email"
|
||||
placeholder={user ? user.email : 'New Email'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.new_email && <div className="text-danger"><small>{errors.new_email.message}</small></div>}
|
||||
</FormGroup>
|
||||
<div className='d-flex align-content-center justify-content-start'>
|
||||
<input type="submit" className="btn btn-primary" value="Save Email" disabled={submitting} />
|
||||
<span className='ml-2'>
|
||||
{ submitting && <FontAwesomeIcon icon="spinner" />}
|
||||
</span>
|
||||
</div>
|
||||
</Form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKEditEmail;
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, CardHeader, CardBody, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuth } from '../../context/UserAuth';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { postUpdateAccountPassword, requestPasswordReset } from '../../helpers/rest';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
const JKEditPassword = ({ setAlert, toggleAlert }) => {
|
||||
const { t } = useTranslation('account');
|
||||
const { currentUser } = useAuth();
|
||||
const [user, setUser] = useState(null);
|
||||
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [showNewPassword, setShowNewPassword] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const {
|
||||
handleSubmit: handleSubmit,
|
||||
control: control,
|
||||
formState: { errors },
|
||||
setError,
|
||||
setValue
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
current_password: '',
|
||||
new_password: ''
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
setUser(currentUser);
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
const onSubmitPassword = data => {
|
||||
setSubmitting(true);
|
||||
const { new_password, current_password } = data;
|
||||
postUpdateAccountPassword(currentUser.id, { current_password, new_password })
|
||||
.then(response => {
|
||||
setAlert('Your password has been successfully updated.');
|
||||
setValue('current_password', '');
|
||||
setValue('new_password', '');
|
||||
toggleAlert();
|
||||
})
|
||||
.catch(async error => {
|
||||
console.log(error);
|
||||
const errorResp = await error.json();
|
||||
console.log(errorResp);
|
||||
if (errorResp.errors) {
|
||||
const errors = errorResp.errors;
|
||||
if (errors.current_password && errors.current_password.length) {
|
||||
errors.current_password.forEach(error => {
|
||||
setError('current_password', {
|
||||
type: 'manual',
|
||||
message: `Current password ${error}`
|
||||
});
|
||||
});
|
||||
}
|
||||
if (errors.password && errors.password.length) {
|
||||
errors.password.forEach(error => {
|
||||
setError('new_password', {
|
||||
type: 'manual',
|
||||
message: `New password ${error}`
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
const requestResetPassword = async (e) => {
|
||||
e.preventDefault()
|
||||
if (!currentUser) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await requestPasswordReset(currentUser.id);
|
||||
setAlert(
|
||||
'A password reset email has been sent to your email. Please check your email and click the link to reset your password.'
|
||||
);
|
||||
toggleAlert();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h5>Password</h5>
|
||||
</CardHeader>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300 }}>
|
||||
<small>
|
||||
To update the password associated with your account, enter your current password (for security reasons) and
|
||||
the new password, and click the "Save Password" button.
|
||||
</small>
|
||||
|
||||
<Form className="mt-2" onSubmit={handleSubmit(onSubmitPassword)}>
|
||||
<FormGroup>
|
||||
<Label for="current_password">Current Password</Label>
|
||||
<Controller
|
||||
name="current_password"
|
||||
control={control}
|
||||
rules={{ required: 'Current password is required' }}
|
||||
render={({ field }) => (
|
||||
<InputGroup>
|
||||
<Input
|
||||
{...field}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
className="form-control"
|
||||
id="current_password"
|
||||
placeholder="Current Password"
|
||||
/>
|
||||
<InputGroupAddon
|
||||
addonType="append"
|
||||
onClick={() => {
|
||||
setShowPassword(!showPassword);
|
||||
}}
|
||||
>
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={showPassword ? 'eye-slash' : 'eye'} />
|
||||
</span>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
)}
|
||||
/>
|
||||
{errors.current_password && (
|
||||
<div className="text-danger">
|
||||
<small>{errors.current_password.message}</small>
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<Label for="new_password">New Password</Label>
|
||||
<Controller
|
||||
name="new_password"
|
||||
control={control}
|
||||
rules={{ required: 'New password is required' }}
|
||||
render={({ field }) => (
|
||||
<InputGroup>
|
||||
<Input
|
||||
{...field}
|
||||
type={showNewPassword ? 'text' : 'password'}
|
||||
className="form-control"
|
||||
id="new_password"
|
||||
placeholder="New Password"
|
||||
/>
|
||||
<InputGroupAddon
|
||||
addonType="append"
|
||||
onClick={() => {
|
||||
setShowNewPassword(!showNewPassword);
|
||||
}}
|
||||
>
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={showNewPassword ? 'eye-slash' : 'eye'} />
|
||||
</span>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
)}
|
||||
/>
|
||||
{errors.new_password && (
|
||||
<div className="text-danger">
|
||||
<small>{errors.new_password.message}</small>
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<div className="d-flex align-content-center justify-content-start">
|
||||
<input type="submit" className="btn btn-primary" value="Save Password" disabled={submitting} />
|
||||
<span className="ml-2">{submitting && <FontAwesomeIcon icon="spinner" />}</span>
|
||||
</div>
|
||||
</Form>
|
||||
<div className="mt-2">
|
||||
<small>
|
||||
If you can not remember your current password, <a href="#" onClick={requestResetPassword}>Click here</a> to reset
|
||||
your password, and you will receive an email with instructions on how to reset your password to the email
|
||||
address associated with your JamKazam account.
|
||||
</small>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKEditPassword;
|
||||
|
|
@ -41,7 +41,6 @@ function secureFetch(path, options) {
|
|||
break;
|
||||
default:
|
||||
console.log('apiFetch Some error occured');
|
||||
break;
|
||||
}
|
||||
//here you also can thorow custom error too
|
||||
reject(response);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ import {
|
|||
faExclamationTriangle,
|
||||
faExternalLinkAlt,
|
||||
faEye,
|
||||
faEyeSlash,
|
||||
faFileAlt,
|
||||
faFileArchive,
|
||||
faFilePdf,
|
||||
|
|
@ -158,7 +159,7 @@ import {
|
|||
faRecordVinyl,
|
||||
faAddressCard,
|
||||
faVolumeUp,
|
||||
faSpinner
|
||||
faSpinner,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
//import { faAcousticGuitar } from "../icons";
|
||||
|
|
@ -245,6 +246,7 @@ library.add(
|
|||
faFilePdf,
|
||||
faFileAlt,
|
||||
faEye,
|
||||
faEyeSlash,
|
||||
faCaretUp,
|
||||
faCodeBranch,
|
||||
faExclamationTriangle,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import apiFetch from "./apiFetch";
|
||||
import apiFetch from './apiFetch';
|
||||
|
||||
export const getMusicians = (page) => {
|
||||
export const getMusicians = page => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/search/musicians?results=true`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
// export const getPeople = (page) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
|
|
@ -16,13 +16,13 @@ export const getMusicians = (page) => {
|
|||
// })
|
||||
// }
|
||||
|
||||
export const getPersonById = (id) => {
|
||||
return new Promise((resolve, reject) => (
|
||||
export const getPersonById = id => {
|
||||
return new Promise((resolve, reject) =>
|
||||
apiFetch(`/users/${id}/profile?show_teacher=true`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
))
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getPeople = ({ data, offset, limit } = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -31,33 +31,33 @@ export const getPeople = ({ data, offset, limit } = {}) => {
|
|||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getPeopleIndex = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getGenres = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch('/genres')
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getInstruments = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch('/instruments')
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
// export const getCurrentUser = () => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
|
|
@ -67,13 +67,13 @@ export const getInstruments = () => {
|
|||
// })
|
||||
// }
|
||||
|
||||
export const getFriends = (userId) => {
|
||||
export const getFriends = userId => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/friends`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const addFriend = (userId, friendId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -82,9 +82,9 @@ export const addFriend = (userId, friendId) => {
|
|||
body: JSON.stringify({ friend_id: friendId })
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const removeFriend = (userId, friendId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -92,97 +92,95 @@ export const removeFriend = (userId, friendId) => {
|
|||
method: 'DELETE'
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getTextMessages = (options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/text_messages?${new URLSearchParams(options)}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const createTextMessage = (options) => {
|
||||
export const createTextMessage = options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/text_messages`, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options)
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const createLobbyChatMessage = (options) => {
|
||||
export const createLobbyChatMessage = options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/chat`, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options)
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getNotifications = (userId, options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/notifications?${new URLSearchParams(options)}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const acceptFriendRequest = (userId, options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { status, friend_request_id } = options
|
||||
const { status, friend_request_id } = options;
|
||||
apiFetch(`/users/${userId}/friend_requests/${friend_request_id}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ status })
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteNotification = (userId, notificationId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/notifications/${notificationId}`, {
|
||||
method: 'DELETE',
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getSessions = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/sessions`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getLatencyToUsers = (currentUserId, participantIds) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const query = participantIds.map(id => `user_ids[]=${id}`).join('&')
|
||||
const query = participantIds.map(id => `user_ids[]=${id}`).join('&');
|
||||
apiFetch(`/users/${currentUserId}/latencies?${query}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getLobbyChatMessages = (options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log('getLobbyChatMessages', options)
|
||||
console.log('getLobbyChatMessages', options);
|
||||
apiFetch(`/chat?${new URLSearchParams(options)}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const updateUser = (userId, options) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -191,31 +189,64 @@ export const updateUser = (userId, options) => {
|
|||
body: JSON.stringify(options)
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getCountries = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/countries`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getRegions = (countryId) => {
|
||||
export const getRegions = countryId => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/regions?country=${countryId}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const getCities = (countryId, regionId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/cities?country=${countryId}®ion=${regionId}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const postUpdateAccountEmail = (userId, options) => {
|
||||
const { email, current_password } = options;
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/update_email`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ update_email: email, current_password })
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const postUpdateAccountPassword = (userId, options) => {
|
||||
const { new_password, current_password } = options;
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/set_password`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ old_password: current_password, new_password, new_password_confirm: new_password })
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const requestPasswordReset = (userId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/users/${userId}/request_reset_password`, {
|
||||
method: 'POST',
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import authTranslationsEN from './locales/en/auth.json'
|
|||
import sessTranslationsEN from './locales/en/sessions.json'
|
||||
import unsubscribeTranslationsEN from './locales/en/unsubscribe.json'
|
||||
import profileEN from './locales/en/profile.json'
|
||||
import accountEN from './locales/en/account.json'
|
||||
|
||||
import commonTranslationsES from './locales/es/common.json'
|
||||
import homeTranslationsES from './locales/es/home.json'
|
||||
|
|
@ -16,6 +17,7 @@ import authTranslationsES from './locales/es/auth.json'
|
|||
import sessTranslationsES from './locales/es/sessions.json'
|
||||
import unsubscribeTranslationsES from './locales/es/unsubscribe.json'
|
||||
import profileES from './locales/es/profile.json'
|
||||
import accountES from './locales/es/account.json'
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
fallbackLng: 'en',
|
||||
|
|
@ -29,7 +31,8 @@ i18n.use(initReactI18next).init({
|
|||
auth: authTranslationsEN,
|
||||
sessions: sessTranslationsEN,
|
||||
unsubscribe: unsubscribeTranslationsEN,
|
||||
profile: profileEN
|
||||
profile: profileEN,
|
||||
account: accountEN
|
||||
},
|
||||
es: {
|
||||
//translations: require('./locales/es/translations.json')
|
||||
|
|
@ -39,7 +42,8 @@ i18n.use(initReactI18next).init({
|
|||
auth: authTranslationsES,
|
||||
sessions: sessTranslationsES,
|
||||
unsubscribe: unsubscribeTranslationsES,
|
||||
profile: profileES
|
||||
profile: profileES,
|
||||
account: accountES
|
||||
}
|
||||
},
|
||||
//ns: ['translations'],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"identity": {
|
||||
"page_title": "Identity",
|
||||
"modals": {
|
||||
"update_notification": {
|
||||
"title": "Account Identity Updated"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ class ApiUsersController < ApiController
|
|||
:friend_show, :friend_destroy, # friends
|
||||
:notification_index, :notification_destroy, # notifications
|
||||
:band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations
|
||||
:set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy,
|
||||
:set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy, :request_reset_password,
|
||||
:share_session, :share_recording,
|
||||
:affiliate_report, :audio_latency, :get_latencies, :broadcast_notification, :redeem_giftcard]
|
||||
|
||||
|
|
@ -333,6 +333,11 @@ class ApiUsersController < ApiController
|
|||
respond_with responder: ApiResponder, :status => 204
|
||||
end
|
||||
|
||||
def request_reset_password
|
||||
User.reset_password(current_user.email, ApplicationHelper.base_uri(request))
|
||||
respond_with current_user, responder: ApiResponder, :status => 200
|
||||
end
|
||||
|
||||
###################### AUTHENTICATION ###################
|
||||
def auth_session_create
|
||||
@user = User.authenticate(params[:email], params[:password])
|
||||
|
|
|
|||
|
|
@ -403,6 +403,7 @@ Rails.application.routes.draw do
|
|||
match '/users/complete/:signup_token' => 'api_users#complete', as: 'complete', via: 'post'
|
||||
match '/users/authorizations/google' => 'api_users#google_auth', :via => :get
|
||||
match '/users/:id/set_password' => 'api_users#set_password', :via => :post
|
||||
match '/users/:id/request_reset_password' => 'api_users#request_reset_password', :via => :post
|
||||
|
||||
match '/reviews' => 'api_reviews#index', :via => :get
|
||||
match '/reviews' => 'api_reviews#create', :via => :post
|
||||
|
|
|
|||
Loading…
Reference in New Issue