Connect create user to the API

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2020-05-19 06:55:06 +02:00 committed by Alexandre Bodin
parent 256540c3ec
commit 899ecc9fe3
4 changed files with 126 additions and 105 deletions

View File

@ -6,16 +6,19 @@ import { Duplicate } from '@buffetjs/icons';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CopyToClipboard } from 'react-copy-to-clipboard'; import { CopyToClipboard } from 'react-copy-to-clipboard';
import basename from '../../../utils/basename';
import IconWrapper from './IconWrapper'; import IconWrapper from './IconWrapper';
import Envelope from './Envelope'; import Envelope from './Envelope';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
const MagicLink = ({ link }) => { const MagicLink = ({ registrationToken }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const handleCopy = () => { const handleCopy = () => {
strapi.notification.info('notification.link-copied'); strapi.notification.info('notification.link-copied');
}; };
const link = `${window.location.origin}${basename}auth/register?code=${registrationToken}`;
return ( return (
<Wrapper> <Wrapper>
<IconWrapper> <IconWrapper>
@ -37,11 +40,11 @@ const MagicLink = ({ link }) => {
}; };
MagicLink.defaultProps = { MagicLink.defaultProps = {
link: 'http://my-app.com/admin/registration?code=1234567827654576856789', registrationToken: '',
}; };
MagicLink.propTypes = { MagicLink.propTypes = {
link: PropTypes.string, registrationToken: PropTypes.string,
}; };
export default MagicLink; export default MagicLink;

View File

@ -1,7 +1,8 @@
import React, { forwardRef, useReducer, useImperativeHandle, useRef } from 'react'; import React, { forwardRef, useReducer, useImperativeHandle, useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { ModalSection } from 'strapi-helper-plugin'; import { ModalSection, request } from 'strapi-helper-plugin';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { get } from 'lodash';
import { Padded, Text } from '@buffetjs/core'; import { Padded, Text } from '@buffetjs/core';
import { Col, Row } from 'reactstrap'; import { Col, Row } from 'reactstrap';
import checkFormValidity from '../../../utils/users/checkFormValidity'; import checkFormValidity from '../../../utils/users/checkFormValidity';
@ -14,121 +15,135 @@ import Wrapper from './Wrapper';
import MagicLink from '../MagicLink'; import MagicLink from '../MagicLink';
// This component accepts a ref so we can have access to the submit handler. // This component accepts a ref so we can have access to the submit handler.
const ModalCreateBody = forwardRef(({ isDisabled, onSubmit, showMagicLink }, ref) => { const ModalCreateBody = forwardRef(
const [reducerState, dispatch] = useReducer(reducer, initialState, init); ({ isDisabled, onSubmit, registrationToken, showMagicLink }, ref) => {
const { formErrors, modifiedData } = reducerState; const [reducerState, dispatch] = useReducer(reducer, initialState, init);
const buttonSubmitRef = useRef(null); const { formErrors, modifiedData } = reducerState;
const buttonSubmitRef = useRef(null);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
submit: () => { submit: () => {
buttonSubmitRef.current.click(); buttonSubmitRef.current.click();
}, },
})); }));
const handleChange = ({ target: { name, value } }) => { const handleChange = ({ target: { name, value } }) => {
dispatch({ dispatch({
type: 'ON_CHANGE', type: 'ON_CHANGE',
keys: name, keys: name,
value, value,
}); });
}; };
const handleSubmit = async e => { const handleSubmit = async e => {
e.persist(); e.persist();
e.preventDefault(); e.preventDefault();
const errors = await checkFormValidity(modifiedData); const errors = await checkFormValidity(modifiedData);
if (!errors) { if (!errors) {
onSubmit(e, modifiedData); try {
const requestURL = '/admin/users';
// TODO post request with errors handling const { data } = await request(requestURL, { method: 'POST', body: modifiedData });
}
dispatch({ onSubmit(e, data);
type: 'SET_ERRORS', } catch (err) {
errors: errors || {}, const message = get(err, ['response', 'payload', 'message'], 'An error occured');
});
};
return ( strapi.notification.error(message);
<form onSubmit={handleSubmit}> }
{/* TODO magic link with token when api ready */}
{showMagicLink && ( // TODO post request with errors handling
}
dispatch({
type: 'SET_ERRORS',
errors: errors || {},
});
};
return (
<form onSubmit={handleSubmit}>
{/* TODO magic link with token when api ready */}
{showMagicLink && (
<ModalSection>
<MagicLink registrationToken={registrationToken} />
</ModalSection>
)}
<ModalSection> <ModalSection>
<MagicLink /> <Padded top size="18px">
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
<FormattedMessage id="app.components.Users.ModalCreateBody.block-title.details">
{txt => txt}
</FormattedMessage>
</Text>
</Padded>
</ModalSection> </ModalSection>
)} <ModalSection>
<ModalSection> <Wrapper>
<Padded top size="18px"> <Padded top size="20px">
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase"> <Row>
<FormattedMessage id="app.components.Users.ModalCreateBody.block-title.details"> {Object.keys(form).map((inputName, i) => (
{txt => txt} <Input
</FormattedMessage> key={inputName}
</Text> {...form[inputName]}
</Padded> autoFocus={i === 0}
</ModalSection> disabled={isDisabled}
<ModalSection> error={formErrors[inputName]}
<Wrapper> name={inputName}
<Padded top size="20px"> onChange={handleChange}
<Row> value={modifiedData[inputName]}
{Object.keys(form).map((inputName, i) => ( />
<Input ))}
key={inputName} </Row>
{...form[inputName]} </Padded>
autoFocus={i === 0} </Wrapper>
disabled={isDisabled} </ModalSection>
error={formErrors[inputName]} <ModalSection>
name={inputName} <Padded top size="3px">
onChange={handleChange} <Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
value={modifiedData[inputName]} <FormattedMessage id="app.components.Users.ModalCreateBody.block-title.roles">
/> {txt => txt}
))} </FormattedMessage>
</Row> </Text>
</Padded> </Padded>
</Wrapper> </ModalSection>
</ModalSection> <ModalSection>
<ModalSection> <Wrapper>
<Padded top size="3px"> <Padded top size="12px">
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase"> <Row>
<FormattedMessage id="app.components.Users.ModalCreateBody.block-title.roles"> <Col xs="6">
{txt => txt} <SelectRoles
</FormattedMessage> isDisabled={isDisabled}
</Text> name="roles"
</Padded> onChange={handleChange}
</ModalSection> value={modifiedData.roles}
<ModalSection> error={formErrors.roles}
<Wrapper> />
<Padded top size="12px"> </Col>
<Row> </Row>
<Col xs="6"> </Padded>
<SelectRoles </Wrapper>
isDisabled={isDisabled} </ModalSection>
name="roles" <button type="submit" style={{ display: 'none' }} ref={buttonSubmitRef}>
onChange={handleChange} hidden button to use the native form event
value={modifiedData.roles} </button>
error={formErrors.roles} </form>
/> );
</Col> }
</Row> );
</Padded>
</Wrapper>
</ModalSection>
<button type="submit" style={{ display: 'none' }} ref={buttonSubmitRef}>
hidden button to use the native form event
</button>
</form>
);
});
ModalCreateBody.defaultProps = { ModalCreateBody.defaultProps = {
isDisabled: false, isDisabled: false,
onSubmit: e => e.preventDefault(), onSubmit: e => e.preventDefault(),
registrationToken: '',
showMagicLink: false, showMagicLink: false,
}; };
ModalCreateBody.propTypes = { ModalCreateBody.propTypes = {
isDisabled: PropTypes.bool, isDisabled: PropTypes.bool,
onSubmit: PropTypes.func, onSubmit: PropTypes.func,
registrationToken: PropTypes.string,
showMagicLink: PropTypes.bool, showMagicLink: PropTypes.bool,
}; };

View File

@ -9,6 +9,7 @@ const ModalForm = ({ isOpen, onClosed, onToggle }) => {
// Little trick to focus the first input // Little trick to focus the first input
// Without this the focus is lost // Without this the focus is lost
const [showBody, setShowBody] = useState(false); const [showBody, setShowBody] = useState(false);
const [registrationToken, setRegistrationToken] = useState(null);
const { formatMessage } = useGlobalContext(); const { formatMessage } = useGlobalContext();
const ref = useRef(null); const ref = useRef(null);
const { buttonSubmitLabel, Component, isDisabled, next } = stepper[currentStep]; const { buttonSubmitLabel, Component, isDisabled, next } = stepper[currentStep];
@ -35,7 +36,10 @@ const ModalForm = ({ isOpen, onClosed, onToggle }) => {
setShowBody(false); setShowBody(false);
}; };
const handleSubmit = () => { const handleSubmit = (e, data) => {
const { registrationToken } = data;
setRegistrationToken(registrationToken);
goNext(); goNext();
}; };
@ -57,6 +61,7 @@ const ModalForm = ({ isOpen, onClosed, onToggle }) => {
isDisabled={isDisabled} isDisabled={isDisabled}
onSubmit={handleSubmit} onSubmit={handleSubmit}
ref={currentStep === 'create' ? ref : null} ref={currentStep === 'create' ? ref : null}
registrationToken={registrationToken}
showMagicLink={currentStep === 'magic-link'} showMagicLink={currentStep === 'magic-link'}
/> />
)} )}

View File

@ -5,17 +5,15 @@ const stepper = {
buttonSubmitLabel: 'app.containers.Users.ModalForm.footer.button-success', buttonSubmitLabel: 'app.containers.Users.ModalForm.footer.button-success',
Component: ModalCreateBody, Component: ModalCreateBody,
isDisabled: false, isDisabled: false,
// next: 'magic-link', next: 'magic-link',
// TODO: set it back to magic-link
next: null,
}, },
'magic-link': { 'magic-link': {
buttonSubmitLabel: 'form.button.continue', buttonSubmitLabel: 'form.button.continue',
Component: ModalCreateBody, Component: ModalCreateBody,
isDisabled: true, isDisabled: true,
next: 'summary', next: null,
}, },
// TODO: I am not sure this step is needed we might need to delete it
summary: { summary: {
buttonSubmitLabel: 'form.button.done', buttonSubmitLabel: 'form.button.done',
Component: () => 'COMING SOON', Component: () => 'COMING SOON',