mirror of
https://github.com/strapi/strapi.git
synced 2025-12-24 13:43:41 +00:00
Resolve conflicts
This commit is contained in:
commit
1ac6a56ce0
1
packages/strapi-admin/.gitignore
vendored
1
packages/strapi-admin/.gitignore
vendored
@ -8,4 +8,3 @@ package-lock.json
|
||||
.DS_Store
|
||||
npm-debug.log
|
||||
.idea
|
||||
manifest.json
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
.logout {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
min-width: 19rem;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
z-index: 999;
|
||||
> div {
|
||||
height: 6rem;
|
||||
width: 100%;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.backHeader {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: 6rem;
|
||||
width: 6.5rem;
|
||||
|
||||
@ -106,3 +106,15 @@
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.descriptionContainer {
|
||||
> div {
|
||||
display: block;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,11 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer
|
||||
<ListRow onClick={this.handleGoTo}>
|
||||
<div className="col-md-1"><i className={`fa ${this.props.rowItem.icon}`} /></div>
|
||||
<div className={`col-md-3 ${styles.italic} ${styles.nameContainer}`}><span style={{ width: spanStyle }}>{startCase(this.props.rowItem.name)} {pluginSource}</span> {temporary}</div>
|
||||
<div className="col-md-5 text-center">{description}</div>
|
||||
<div className={`col-md-5 text-center ${styles.descriptionContainer}`}>
|
||||
<div>
|
||||
{description}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2 text-center">{this.props.rowItem.fields}</div>
|
||||
<div className="col-md-1">
|
||||
<IcoContainer icons={icons} />
|
||||
|
||||
@ -18,16 +18,17 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
||||
<div className={styles.editForm}>
|
||||
<div className="row">
|
||||
<Input
|
||||
label="users-permissions.EditForm.inputToggle.label"
|
||||
inputDescription="users-permissions.EditForm.inputToggle.description"
|
||||
name="uniqueAccount"
|
||||
label="users-permissions.EditForm.inputToggle.label.email"
|
||||
inputDescription="users-permissions.EditForm.inputToggle.description.email"
|
||||
name="unique_email"
|
||||
onChange={this.props.onChange}
|
||||
type="toggle"
|
||||
value={get(this.props.values, 'uniqueAccount')}
|
||||
value={get(this.props.values, 'unique_email')}
|
||||
validations={{}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.separator} />
|
||||
{/*}
|
||||
<div className="row">
|
||||
<Input
|
||||
customBootstrapClass="col-md-3"
|
||||
@ -51,8 +52,20 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
||||
value={get(this.props.values, 'durations')}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.separator} />
|
||||
*/}
|
||||
<div className="row">
|
||||
<Input
|
||||
label="users-permissions.EditForm.inputToggle.label.sign-up"
|
||||
inputDescription="users-permissions.EditForm.inputToggle.description.sign-up"
|
||||
name="allow_register"
|
||||
onChange={this.props.onChange}
|
||||
type="toggle"
|
||||
value={get(this.props.values, 'allow_register')}
|
||||
validations={{}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,18 +20,18 @@ const links = [
|
||||
name: 'users-permissions.HeaderNav.link.roles',
|
||||
to: '/plugins/users-permissions/roles',
|
||||
},
|
||||
// {
|
||||
// name: 'users-permissions.HeaderNav.link.providers',
|
||||
// to: '/plugins/users-permissions/providers',
|
||||
// },
|
||||
// {
|
||||
// name: 'users-permissions.HeaderNav.link.emailTemplates',
|
||||
// to: '/plugins/users-permissions/email-templates',
|
||||
// },
|
||||
// {
|
||||
// name: 'users-permissions.HeaderNav.link.advancedSettings',
|
||||
// to: '/plugins/users-permissions/advanced-settings',
|
||||
// },
|
||||
{
|
||||
name: 'users-permissions.HeaderNav.link.providers',
|
||||
to: '/plugins/users-permissions/providers',
|
||||
},
|
||||
{
|
||||
name: 'users-permissions.HeaderNav.link.emailTemplates',
|
||||
to: '/plugins/users-permissions/email-templates',
|
||||
},
|
||||
{
|
||||
name: 'users-permissions.HeaderNav.link.advancedSettings',
|
||||
to: '/plugins/users-permissions/advanced',
|
||||
},
|
||||
];
|
||||
|
||||
function HeaderNav() {
|
||||
|
||||
@ -48,7 +48,7 @@ const generateListTitle = (data, settingType) => {
|
||||
}
|
||||
};
|
||||
|
||||
function List({ data, deleteData, noButton, onButtonClick, settingType }) {
|
||||
function List({ data, deleteData, noButton, onButtonClick, settingType, values }) {
|
||||
return (
|
||||
<div className={styles.list}>
|
||||
<div className={styles.flex}>
|
||||
@ -73,6 +73,7 @@ function List({ data, deleteData, noButton, onButtonClick, settingType }) {
|
||||
item={item}
|
||||
key={item.name}
|
||||
settingType={settingType}
|
||||
values={values}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
@ -92,6 +93,7 @@ List.propTypes = {
|
||||
noButton: PropTypes.bool,
|
||||
onButtonClick: PropTypes.func,
|
||||
settingType: PropTypes.string.isRequired,
|
||||
values: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default List;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { get, includes } from 'lodash';
|
||||
import { router } from 'app';
|
||||
|
||||
@ -14,6 +15,7 @@ import { router } from 'app';
|
||||
import IcoContainer from 'components/IcoContainer';
|
||||
import PopUpWarning from 'components/PopUpWarning';
|
||||
|
||||
import en from 'translations/en.json';
|
||||
import styles from './styles.scss';
|
||||
|
||||
class ListRow extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
@ -70,12 +72,14 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
||||
</div>
|
||||
);
|
||||
case 'providers':
|
||||
icons.pop(); // Remove the icon-trash
|
||||
|
||||
return (
|
||||
<div className={cn('row', styles.wrapper)}>
|
||||
<div className="col-md-4">
|
||||
<div className={styles.flex}>
|
||||
<div>
|
||||
<i className={`fa fa-${this.props.item.ico}`} />
|
||||
<i className={`fa fa-${this.props.item.icon}`} />
|
||||
</div>
|
||||
<div>
|
||||
{this.props.item.name}
|
||||
@ -83,7 +87,7 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-6" style={{ fontWeight: '500' }}>
|
||||
{this.props.item.enabled ? (
|
||||
{get(this.props.values, [get(this.props.item, 'name'), 'enabled']) ? (
|
||||
<span style={{ color: '#5A9E06' }}>Enabled</span>
|
||||
) : (
|
||||
<span style={{ color: '#F64D0A' }}>Disabled</span>
|
||||
@ -96,22 +100,19 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
||||
);
|
||||
|
||||
case 'email-templates':
|
||||
icons = [
|
||||
{
|
||||
icoType: 'pencil',
|
||||
onClick: this.handleClick,
|
||||
},
|
||||
];
|
||||
icons.pop();
|
||||
|
||||
return (
|
||||
<div className={cn('row', styles.wrapper)}>
|
||||
<div className="col-md-4">
|
||||
<div className={styles.flex}>
|
||||
<div>
|
||||
<i className={`fa fa-${this.props.item.ico}`} />
|
||||
<i className={`fa fa-${this.props.item.icon}`} />
|
||||
</div>
|
||||
<div>
|
||||
{this.props.item.name}
|
||||
{this.props.item.display && en[this.props.item.display] ? (
|
||||
<FormattedMessage id={`users-permissions.${this.props.item.display}`} />
|
||||
): this.props.item.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -136,7 +137,7 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
||||
}
|
||||
case 'providers':
|
||||
case 'email-templates':
|
||||
return router.push(`${router.location.pathname}#edit::${this.props.settingType}::${this.props.item.id}`);
|
||||
return this.context.setDataToEdit(this.props.item.name);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -163,11 +164,16 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
|
||||
}
|
||||
}
|
||||
|
||||
ListRow.contextTypes = {
|
||||
setDataToEdit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
ListRow.defaultProps = {
|
||||
item: {
|
||||
name: 'Owner',
|
||||
description: 'Rule them all. This role can\'t be deleted',
|
||||
nb_users: 1,
|
||||
icon: 'envelope',
|
||||
},
|
||||
settingType: 'roles',
|
||||
};
|
||||
@ -176,6 +182,7 @@ ListRow.propTypes = {
|
||||
deleteData: PropTypes.func.isRequired,
|
||||
item: PropTypes.object,
|
||||
settingType: PropTypes.string,
|
||||
values: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ListRow;
|
||||
|
||||
@ -8,127 +8,195 @@ import React from 'react';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get } from 'lodash';
|
||||
import { router } from 'app';
|
||||
import {
|
||||
capitalize,
|
||||
get,
|
||||
findIndex,
|
||||
isArray,
|
||||
isEmpty,
|
||||
isObject,
|
||||
includes,
|
||||
map,
|
||||
startsWith,
|
||||
tail,
|
||||
take,
|
||||
takeRight,
|
||||
} from 'lodash';
|
||||
|
||||
// Translations
|
||||
import en from 'translations/en.json';
|
||||
|
||||
import Input from 'components/Input';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
class PopUpForm extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
toggleModal = () => router.push(router.location.pathname);
|
||||
state = { enabled: false, isEditing: false };
|
||||
|
||||
renderButton = () => {
|
||||
if (this.props.showLoader) {
|
||||
return (
|
||||
<Button onClick={() => {}} type="submit" className={styles.primary} disabled>
|
||||
<p className={styles.saving}>
|
||||
<span>.</span><span>.</span><span>.</span>
|
||||
</p>
|
||||
</Button>
|
||||
);
|
||||
getRedirectURIProviderConf = () => { // NOTE: Still testings providers so the switch statement is likely to change
|
||||
switch (this.props.dataToEdit) {
|
||||
case 'facebook':
|
||||
return `${strapi.backendURL}/connect/facebook/callback`;
|
||||
case 'github':
|
||||
return get(this.props.values, 'redirect_uri', '');
|
||||
default: {
|
||||
const value = get(this.props.values, 'callback', '');
|
||||
|
||||
return startsWith(value, 'http') ? value : `${strapi.backendURL}${value}`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button type="submit" onClick={this.props.onSubmit} className={styles.primary}>
|
||||
<FormattedMessage id="users-permissions.PopUpForm.button.save" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
generateRedirectURL = (url) => {
|
||||
return startsWith(url, 'https://') || startsWith(url, 'http://') || this.state.isEditing ? url : `${strapi.backendURL}${startsWith(url, '/') ? '' : '/'}${url}`;
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({ enabled: e.target.value });
|
||||
this.props.onChange(e);
|
||||
}
|
||||
|
||||
handleBlur = (e) => {
|
||||
this.setState({ isEditing: false });
|
||||
|
||||
if (isEmpty(e.target.value)) {
|
||||
const { name, type } = e.target;
|
||||
const target = Object.assign({ name, type }, { value: `/auth/${this.props.dataToEdit}/callback` });
|
||||
this.props.onChange({ target });
|
||||
}
|
||||
}
|
||||
|
||||
handleFocus = () => this.setState({ isEditing: true });
|
||||
|
||||
renderForm = () => {
|
||||
if (this.props.settingType === 'providers') {
|
||||
const { dataToEdit, settingType, values } = this.props;
|
||||
const form = Object.keys(values.options || values || {}).reduce((acc, current) => {
|
||||
const path = settingType === 'email-templates' ? ['options', current] : [ current ];
|
||||
const name = settingType === 'email-templates' ? 'options.' : '';
|
||||
|
||||
if (isObject(get(values, path)) && !isArray(get(values, path))) {
|
||||
return Object.keys(get(values, path, {}))
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(`${name}${current}.${curr}`);
|
||||
|
||||
return acc;
|
||||
}, []).concat(acc);
|
||||
} else if (current !== 'icon' && current !== 'scope'){
|
||||
acc.push(`${name}${current}`);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (settingType === 'providers') {
|
||||
return (
|
||||
<div className="row">
|
||||
<Input
|
||||
autoFocus
|
||||
label="users-permissions.PopUpForm.inputSelect.providers.label"
|
||||
name="provider"
|
||||
onChange={this.props.onChange}
|
||||
selectOptions={[{ value: 'Email'}, { value: 'Facebook' }, { value: 'Google' }]}
|
||||
type="select"
|
||||
validations={{ required: true }}
|
||||
value={get(this.props.values, 'provider')}
|
||||
/>
|
||||
<div className="col-md-6" />
|
||||
<Input
|
||||
inputDescription="users-permissions.PopUpForm.inputToggle.providers.description"
|
||||
label="users-permissions.PopUpForm.inputToggle.providers.label"
|
||||
name="enabled"
|
||||
onChange={this.props.onChange}
|
||||
inputDescription="users-permissions.PopUpForm.Providers.enabled.description"
|
||||
label="users-permissions.PopUpForm.Providers.enabled.label"
|
||||
name={`${dataToEdit}.enabled`}
|
||||
onChange={this.handleChange}
|
||||
type="toggle"
|
||||
validations={{}}
|
||||
value={get(this.props.values, 'enabled')}
|
||||
value={get(this.props.values, 'enabled', this.state.enabled)}
|
||||
/>
|
||||
{form.length > 1 ? (
|
||||
<div className={styles.separator} />
|
||||
|
||||
) : ''}
|
||||
{map(tail(form), (value, key) => (
|
||||
<Input
|
||||
autoFocus={key === 0}
|
||||
customBootstrapClass="col-md-12"
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
errors={get(this.props.formErrors, [findIndex(this.props.formErrors, ['name', value]), 'errors'], [])}
|
||||
key={value}
|
||||
label={`users-permissions.PopUpForm.Providers.${ includes(value, 'callback') || includes(value, 'redirect_uri') ? 'redirectURL.front-end' : value}.label`}
|
||||
name={`${dataToEdit}.${value}`}
|
||||
onFocus={includes(value, 'callback') || includes(value, 'redirect_uri') ? this.handleFocus : () => {}}
|
||||
onBlur={includes(value, 'callback') || includes(value, 'redirect_uri') ? this.handleBlur : false}
|
||||
onChange={this.props.onChange}
|
||||
type="text"
|
||||
value={includes(value, 'callback') || includes(value, 'redirect_uri') ? this.generateRedirectURL(get(values, value)) : get(values, value)}
|
||||
validations={{ required: true }}
|
||||
/>
|
||||
))}
|
||||
{ dataToEdit !== 'email' ? (
|
||||
<Input
|
||||
customBootstrapClass="col-md-12"
|
||||
disabled
|
||||
label={`users-permissions.PopUpForm.Providers.${dataToEdit}.providerConfig.redirectURL`}
|
||||
name="noName"
|
||||
type="text"
|
||||
onChange={() => {}}
|
||||
value={this.getRedirectURIProviderConf()}
|
||||
validations={{}}
|
||||
/>
|
||||
) : ''}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<Input
|
||||
autoFocus
|
||||
label="users-permissions.PopUpForm.inputText.shipperName.label"
|
||||
name="shipperName"
|
||||
onChange={this.props.onChange}
|
||||
value={get(this.props.values, 'shipperName')}
|
||||
placeholder="users-permissions.PopUpForm.inputText.shipperName.placeholder"
|
||||
type="text"
|
||||
validations={{}}
|
||||
/>
|
||||
<Input
|
||||
label="users-permissions.PopUpForm.inputEmail.shipperEmail.label"
|
||||
name="shipperEmail"
|
||||
onChange={this.props.onChange}
|
||||
placeholder="users-permissions.PopUpForm.inputEmail.placeholder"
|
||||
type="email"
|
||||
validations={{ required: true }}
|
||||
value={get(this.props.values, 'shipperEmail')}
|
||||
/>
|
||||
<Input
|
||||
label="users-permissions.PopUpForm.inputEmail.responseEmail.label"
|
||||
name="responseEmail"
|
||||
onChange={this.props.onChange}
|
||||
placeholder="users-permissions.PopUpForm.inputEmail.placeholder"
|
||||
type="email"
|
||||
validations={{}}
|
||||
value={get(this.props.values, 'responseEmail')}
|
||||
/>
|
||||
{map(take(form, 3), (value, key) => (
|
||||
<Input
|
||||
autoFocus={key === 0}
|
||||
key={value}
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
errors={get(this.props.formErrors, [findIndex(this.props.formErrors, ['name', value]), 'errors'], [])}
|
||||
label={`users-permissions.PopUpForm.Email.${value}.label`}
|
||||
name={`${dataToEdit}.${value}`}
|
||||
onChange={this.props.onChange}
|
||||
placeholder={`users-permissions.PopUpForm.Email.${value}.placeholder`}
|
||||
type={includes(value, 'email') ? 'email' : 'text'}
|
||||
value={get(values, value)}
|
||||
validations={value !== 'options.response_email' ? { required: true } : {}}
|
||||
/>
|
||||
))}
|
||||
<div className="col-md-6" />
|
||||
<Input
|
||||
customBootstrapClass="col-md-12"
|
||||
label="users-permissions.PopUpForm.inputText.emailObject.label"
|
||||
name="emailObject"
|
||||
onChange={this.props.onChange}
|
||||
placeholder="users-permissions.PopUpForm.inputText.emailObject.placeholder"
|
||||
type="text"
|
||||
validations={{}}
|
||||
value={get(this.props.values, 'emailObject')}
|
||||
/>
|
||||
<Input
|
||||
customBootstrapClass="col-md-12"
|
||||
label="users-permissions.PopUpForm.inputTextArea.message.label"
|
||||
name="message"
|
||||
onChange={this.props.onChange}
|
||||
placeholder="users-permissions.PopUpForm.inputTextArea.message.placeholder"
|
||||
type="textarea"
|
||||
validations={{}}
|
||||
value={get(this.props.values, 'message')}
|
||||
/>
|
||||
{map(takeRight(form, 2), (value) => (
|
||||
<Input
|
||||
key={value}
|
||||
customBootstrapClass="col-md-12"
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
errors={get(this.props.formErrors, [findIndex(this.props.formErrors, ['name', value]), 'errors'], [])}
|
||||
label={`users-permissions.PopUpForm.Email.${value}.label`}
|
||||
name={`${dataToEdit}.${value}`}
|
||||
inputDescription={includes(value, 'object') ? 'users-permissions.PopUpForm.Email.email_templates.inputDescription' : ''}
|
||||
linkContent={includes(value, 'object') ? { link: 'https://strapi.io/documentation/plugin-development/ui-components.html', description: 'users-permissions.PopUpForm.Email.link.documentation' } : {}}
|
||||
onChange={this.props.onChange}
|
||||
placeholder={`users-permissions.PopUpForm.Email.${this.props.dataToEdit}.${value}.placeholder`}
|
||||
type={includes(value, 'object') ? 'text' : 'textarea'}
|
||||
validations={{ required: true }}
|
||||
value={get(values, value)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { display } = this.props.values;
|
||||
const { actionType, dataToEdit, settingType } = this.props;
|
||||
|
||||
let header = <span>{dataToEdit}</span>;
|
||||
|
||||
if (actionType) {
|
||||
header = <FormattedMessage id={`users-permissions.PopUpForm.header.${actionType}.${settingType}`} values={{ provider: <i>{capitalize(dataToEdit)}</i> }} />;
|
||||
}
|
||||
|
||||
if (display && en[display]) {
|
||||
header = <FormattedMessage id={`users-permissions.${display}`} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.popUpForm}>
|
||||
<Modal isOpen={this.props.isOpen} toggle={this.toggleModal} className={`${styles.modalPosition}`}>
|
||||
<ModalHeader toggle={this.toggleModal} className={styles.modalHeader} />
|
||||
<Modal isOpen={this.props.isOpen} toggle={this.context.unsetDataToEdit} className={`${styles.modalPosition}`}>
|
||||
<ModalHeader toggle={this.context.unsetDataToEdit} className={styles.modalHeader} />
|
||||
<div className={styles.headerContainer}>
|
||||
<div>
|
||||
{this.props.actionType ? (
|
||||
<FormattedMessage id={`users-permissions.PopUpForm.header.${this.props.actionType}.${this.props.settingType}`} />
|
||||
) : <div />}
|
||||
{header}
|
||||
</div>
|
||||
</div>
|
||||
<form onSubmit={this.props.onSubmit}>
|
||||
@ -138,10 +206,12 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<Button onClick={() => router.push(router.location.pathname)} className={styles.secondary}>
|
||||
<Button onClick={() => this.context.unsetDataToEdit()} className={styles.secondary}>
|
||||
<FormattedMessage id="users-permissions.PopUpForm.button.cancel" />
|
||||
</Button>
|
||||
{this.renderButton()}
|
||||
<Button type="submit" onClick={this.props.onSubmit} className={styles.primary}>
|
||||
<FormattedMessage id="users-permissions.PopUpForm.button.save" />
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
</Modal>
|
||||
@ -150,18 +220,25 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
|
||||
}
|
||||
}
|
||||
|
||||
PopUpForm.contextTypes = {
|
||||
unsetDataToEdit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
PopUpForm.defaultProps = {
|
||||
settingType: 'providers',
|
||||
showLoader: false,
|
||||
// showLoader: false,
|
||||
};
|
||||
|
||||
PopUpForm.propTypes = {
|
||||
actionType: PropTypes.string.isRequired,
|
||||
dataToEdit: PropTypes.string.isRequired,
|
||||
didCheckErrors: PropTypes.bool.isRequired,
|
||||
formErrors: PropTypes.array.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
settingType: PropTypes.string,
|
||||
showLoader: PropTypes.bool,
|
||||
// showLoader: PropTypes.bool,
|
||||
values: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@ -164,3 +164,9 @@
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
width: 100%;
|
||||
margin: 14px 15px 20px 15px;
|
||||
border-bottom: 2px solid #F6F6F6;
|
||||
}
|
||||
|
||||
@ -3,17 +3,29 @@
|
||||
* HomePage actions
|
||||
*
|
||||
*/
|
||||
import { Map } from 'immutable';
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
import { isArray } from 'lodash';
|
||||
import {
|
||||
CANCEL_CHANGES,
|
||||
DELETE_DATA,
|
||||
DELETE_DATA_SUCCEEDED,
|
||||
FETCH_DATA,
|
||||
FETCH_DATA_SUCCEEDED,
|
||||
ON_CHANGE,
|
||||
SET_DATA_TO_EDIT,
|
||||
SET_FORM,
|
||||
SET_FORM_ERRORS,
|
||||
SUBMIT,
|
||||
SUBMIT_SUCCEEDED,
|
||||
UNSET_DATA_TO_EDIT,
|
||||
} from './constants';
|
||||
|
||||
export function cancelChanges() {
|
||||
return {
|
||||
type: CANCEL_CHANGES,
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteData(dataToDelete, deleteEndPoint) {
|
||||
return {
|
||||
type: DELETE_DATA,
|
||||
@ -37,57 +49,72 @@ export function fetchData(endPoint) {
|
||||
}
|
||||
|
||||
export function fetchDataSucceeded(data) {
|
||||
if (!isArray(data)) {
|
||||
const list = Object.keys(data).reduce((acc, current) => {
|
||||
const obj = Object.assign({ name: current}, data[current]);
|
||||
acc.push(obj);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
type: FETCH_DATA_SUCCEEDED,
|
||||
data: list,
|
||||
modifiedData: fromJS(data),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: FETCH_DATA_SUCCEEDED,
|
||||
data,
|
||||
modifiedData: fromJS({}),
|
||||
};
|
||||
}
|
||||
|
||||
export function onChange({ target }) {
|
||||
return {
|
||||
type: ON_CHANGE,
|
||||
key: target.name,
|
||||
keys: ['modifiedData'].concat(target.name.split('.')),
|
||||
value: target.value,
|
||||
};
|
||||
}
|
||||
|
||||
export function setForm(formType) {
|
||||
const form = generateForm(formType);
|
||||
export function setDataToEdit(dataToEdit) {
|
||||
return {
|
||||
type: SET_FORM,
|
||||
form,
|
||||
type: SET_DATA_TO_EDIT,
|
||||
dataToEdit,
|
||||
};
|
||||
}
|
||||
|
||||
// Utils
|
||||
|
||||
function generateForm(formType) {
|
||||
let form = Map({});
|
||||
switch (formType) {
|
||||
case 'providers':
|
||||
form = Map({
|
||||
provider: 'Facebook',
|
||||
enabled: false,
|
||||
});
|
||||
break;
|
||||
case 'email-templates':
|
||||
form = Map({
|
||||
shipperName: '',
|
||||
shipperEmail: '',
|
||||
responseEmail: '',
|
||||
emailObject: '',
|
||||
message: '',
|
||||
});
|
||||
break;
|
||||
case 'advanced-settings':
|
||||
form = Map({
|
||||
uniqueAccount: false,
|
||||
subscriptions: '100',
|
||||
durations: '24',
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return form;
|
||||
export function setForm(data) {
|
||||
return {
|
||||
type: SET_FORM,
|
||||
form: fromJS(data),
|
||||
};
|
||||
}
|
||||
|
||||
export function setFormErrors(formErrors) {
|
||||
return {
|
||||
type: SET_FORM_ERRORS,
|
||||
formErrors,
|
||||
};
|
||||
}
|
||||
|
||||
export function submit(endPoint) {
|
||||
return {
|
||||
type: SUBMIT,
|
||||
endPoint,
|
||||
};
|
||||
}
|
||||
|
||||
export function submitSucceeded() {
|
||||
return {
|
||||
type: SUBMIT_SUCCEEDED,
|
||||
};
|
||||
}
|
||||
|
||||
export function unsetDataToEdit() {
|
||||
return {
|
||||
type: UNSET_DATA_TO_EDIT,
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
import { get, isEmpty, isObject } from 'lodash';
|
||||
|
||||
export default function checkFormValidity(settingType, data) {
|
||||
const formErrors = [];
|
||||
|
||||
switch (settingType) {
|
||||
case 'providers': {
|
||||
const isProviderEnabled = get(data, 'enabled');
|
||||
const keys = [ 'key', 'secret' ];
|
||||
|
||||
keys.map(key => {
|
||||
if (isProviderEnabled && isEmpty(get(data, key))) {
|
||||
formErrors.push({ name: key, errors: [{ id: 'components.Input.error.validation.required' }] });
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'email-templates': {
|
||||
Object.keys(data.options).map((value) => {
|
||||
if (isObject(data.options[value])) {
|
||||
Object.keys(data.options[value]).map(subValue => {
|
||||
if (isEmpty(get(data, ['options', value, subValue]))) {
|
||||
formErrors.push({ name: `options.${value}.${subValue}`, errors: [{ id: 'components.Input.error.validation.required' }] });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (value !== 'response_email' && isEmpty(get(data, ['options', value]))) {
|
||||
formErrors.push({ name: `options.${value}`, errors: [{ id: 'components.Input.error.validation.required' }] });
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return formErrors;
|
||||
}
|
||||
@ -4,9 +4,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
export const CANCEL_CHANGES = 'UsersPermissions/HomePage/CANCEL_CHANGES';
|
||||
export const DELETE_DATA = 'UsersPermissions/HomePage/DELETE_DATA';
|
||||
export const DELETE_DATA_SUCCEEDED = 'UsersPermissions/HomePage/DELETE_DATA_SUCCEEDED';
|
||||
export const FETCH_DATA = 'UsersPermissions/HomePage/FETCH_DATA';
|
||||
export const FETCH_DATA_SUCCEEDED = 'UsersPermissions/HomePage/FETCH_DATA_SUCCEEDED';
|
||||
export const ON_CHANGE = 'UsersPermissions/HomePage/ON_CHANGE';
|
||||
export const SET_DATA_TO_EDIT = 'UsersPermissions/HomePage/SET_DATA_TO_EDIT';
|
||||
export const SET_FORM = 'UsersPermissions/HomePage/SET_FORM';
|
||||
export const SET_FORM_ERRORS = 'UsersPermissions/HomePage/SET_FORM_ERRORS';
|
||||
export const SUBMIT = 'UsersPermissions/HomePage/SUBMIT';
|
||||
export const SUBMIT_SUCCEEDED = 'UsersPermissions/HomePage/SUBMIT_SUCCEEDED';
|
||||
export const UNSET_DATA_TO_EDIT = 'UsersPermissions/HomePage/UNSET_DATA_TO_EDIT';
|
||||
|
||||
@ -10,7 +10,7 @@ import { connect } from 'react-redux';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import cn from 'classnames';
|
||||
import { clone, includes, isEmpty, replace } from 'lodash';
|
||||
import { clone, get, includes, isEqual, isEmpty } from 'lodash';
|
||||
|
||||
// Design
|
||||
import EditForm from 'components/EditForm';
|
||||
@ -31,18 +31,32 @@ import styles from './styles.scss';
|
||||
|
||||
// Actions
|
||||
import {
|
||||
cancelChanges,
|
||||
deleteData,
|
||||
fetchData,
|
||||
onChange,
|
||||
setDataToEdit,
|
||||
setFormErrors,
|
||||
submit,
|
||||
unsetDataToEdit,
|
||||
} from './actions';
|
||||
|
||||
import reducer from './reducer';
|
||||
import saga from './saga';
|
||||
|
||||
import checkFormValidity from './checkFormValidity';
|
||||
|
||||
const keyBoardShortCuts = [18, 78];
|
||||
|
||||
export class HomePage extends React.Component {
|
||||
state = { mapKey: {} };
|
||||
state = { mapKey: {}, showModalEdit: false };
|
||||
|
||||
getChildContext = () => (
|
||||
{
|
||||
setDataToEdit: this.props.setDataToEdit,
|
||||
unsetDataToEdit: this.props.unsetDataToEdit,
|
||||
}
|
||||
);
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchData(this.props.match.params.settingType);
|
||||
@ -50,8 +64,14 @@ export class HomePage extends React.Component {
|
||||
document.addEventListener('keyup', this.handleKeyBoardShortCut);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.dataToEdit !== this.props.dataToEdit) {
|
||||
this.setState({ showModalEdit: !isEmpty(nextProps.dataToEdit) });
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
const allowedPaths = ['roles', 'providers', 'email-templates', 'advanced-settings'];
|
||||
const allowedPaths = ['roles', 'providers', 'email-templates', 'advanced'];
|
||||
const shouldRedirect = allowedPaths.filter(el => el === nextProps.match.params.settingType).length === 0;
|
||||
|
||||
if (shouldRedirect) {
|
||||
@ -90,6 +110,7 @@ export class HomePage extends React.Component {
|
||||
}
|
||||
|
||||
handleButtonClick = () => {
|
||||
// TODO change open modal URL
|
||||
if (this.props.match.params.settingType === 'roles') {
|
||||
this.props.history.push(`${this.props.location.pathname}/create`);
|
||||
} else if (this.props.match.params.settingType === 'providers') {
|
||||
@ -97,44 +118,59 @@ export class HomePage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const modifiedObject = get(this.props.modifiedData, this.props.dataToEdit);
|
||||
const initObject = get(this.props.initialData, this.props.dataToEdit);
|
||||
const formErrors = checkFormValidity(this.props.match.params.settingType, modifiedObject);
|
||||
|
||||
if (isEqual(initObject, modifiedObject)) {
|
||||
return this.props.unsetDataToEdit();
|
||||
}
|
||||
|
||||
if (isEmpty(formErrors)) {
|
||||
this.setState({ showModalEdit: false });
|
||||
this.props.submit(this.props.match.params.settingType);
|
||||
} else {
|
||||
this.props.setFormErrors(formErrors);
|
||||
}
|
||||
}
|
||||
|
||||
pluginHeaderActions = [
|
||||
{
|
||||
label: 'users-permissions.EditPage.cancel',
|
||||
kind: 'secondary',
|
||||
onClick: () => {},
|
||||
onClick: () => this.props.cancelChanges(),
|
||||
type: 'button',
|
||||
},
|
||||
{
|
||||
kind: 'primary',
|
||||
label: 'users-permissions.EditPage.submit',
|
||||
onClick: () => {},
|
||||
onClick: () => this.props.submit(this.props.match.params.settingType),
|
||||
type: 'submit',
|
||||
},
|
||||
];
|
||||
|
||||
render() {
|
||||
const headerActions = this.props.match.params.settingType === 'advanced-settings' && this.props.showButtons ?
|
||||
const { didCheckErrors, formErrors, modifiedData, initialData, match, dataToEdit } = this.props;
|
||||
const headerActions = match.params.settingType === 'advanced' && !isEqual(modifiedData, initialData) ?
|
||||
this.pluginHeaderActions : [];
|
||||
const noButtonList = this.props.match.params.settingType === 'email-templates';
|
||||
const component = this.props.match.params.settingType === 'advanced-settings' ?
|
||||
<EditForm onChange={this.props.onChange} values={this.props.modifiedData} /> : (
|
||||
const noButtonList = match.params.settingType === 'email-templates' || match.params.settingType === 'providers';
|
||||
const component = match.params.settingType === 'advanced' ?
|
||||
<EditForm onChange={this.props.onChange} values={modifiedData} /> : (
|
||||
<List
|
||||
data={this.props.data}
|
||||
deleteData={this.props.deleteData}
|
||||
noButton={noButtonList}
|
||||
onButtonClick={this.handleButtonClick}
|
||||
settingType={this.props.match.params.settingType}
|
||||
settingType={match.params.settingType}
|
||||
values={modifiedData}
|
||||
/>
|
||||
);
|
||||
const hashArray = replace(this.props.location.hash, '#', '').split('::');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<form onSubmit={(e) => e.preventDefault()}>
|
||||
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||
<PluginHeader
|
||||
title={{ id: 'users-permissions.HomePage.header.title' }}
|
||||
@ -145,14 +181,15 @@ export class HomePage extends React.Component {
|
||||
{component}
|
||||
</div>
|
||||
<PopUpForm
|
||||
actionType={hashArray[0]}
|
||||
isOpen={!isEmpty(this.props.location.hash)}
|
||||
actionType={'edit'}
|
||||
isOpen={this.state.showModalEdit}
|
||||
dataToEdit={dataToEdit}
|
||||
didCheckErrors={didCheckErrors}
|
||||
formErrors={formErrors}
|
||||
onChange={this.props.onChange}
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
settingType={hashArray[1]}
|
||||
values={this.props.modifiedData}
|
||||
onSubmit={this.handleSubmit}
|
||||
settingType={match.params.settingType}
|
||||
values={modifiedData[dataToEdit] || {}}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
@ -160,28 +197,46 @@ export class HomePage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
HomePage.childContextTypes = {
|
||||
setDataToEdit: PropTypes.func,
|
||||
unsetDataToEdit: PropTypes.func,
|
||||
};
|
||||
|
||||
HomePage.defaultProps = {};
|
||||
|
||||
HomePage.propTypes = {
|
||||
cancelChanges: PropTypes.func.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
dataToEdit: PropTypes.string.isRequired,
|
||||
deleteData: PropTypes.func.isRequired,
|
||||
didCheckErrors: PropTypes.bool.isRequired,
|
||||
didDeleteData: PropTypes.bool.isRequired,
|
||||
fetchData: PropTypes.func.isRequired,
|
||||
formErrors: PropTypes.array.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
initialData: PropTypes.object.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
modifiedData: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
showButtons: PropTypes.bool.isRequired,
|
||||
setDataToEdit: PropTypes.func.isRequired,
|
||||
setFormErrors: PropTypes.func.isRequired,
|
||||
submit: PropTypes.func.isRequired,
|
||||
unsetDataToEdit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{
|
||||
cancelChanges,
|
||||
deleteData,
|
||||
fetchData,
|
||||
onChange,
|
||||
setDataToEdit,
|
||||
setFormErrors,
|
||||
submit,
|
||||
unsetDataToEdit,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
@ -7,16 +7,22 @@
|
||||
import { fromJS, List, Map } from 'immutable';
|
||||
|
||||
import {
|
||||
CANCEL_CHANGES,
|
||||
DELETE_DATA,
|
||||
DELETE_DATA_SUCCEEDED,
|
||||
FETCH_DATA_SUCCEEDED,
|
||||
ON_CHANGE,
|
||||
SET_DATA_TO_EDIT,
|
||||
SET_FORM,
|
||||
SET_FORM_ERRORS,
|
||||
SUBMIT_SUCCEEDED,
|
||||
UNSET_DATA_TO_EDIT,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
data: List([]),
|
||||
dataToDelete: Map({}),
|
||||
dataToEdit: '',
|
||||
deleteEndPoint: '',
|
||||
initialData: Map({}),
|
||||
modifiedData: Map({}),
|
||||
@ -26,6 +32,10 @@ const initialState = fromJS({
|
||||
|
||||
function homePageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case CANCEL_CHANGES:
|
||||
return state
|
||||
.set('formErrors', List([]))
|
||||
.update('modifiedData', () => state.get('initialData'));
|
||||
case DELETE_DATA:
|
||||
return state
|
||||
.set('dataToDelete', Map(action.dataToDelete))
|
||||
@ -37,15 +47,34 @@ function homePageReducer(state = initialState, action) {
|
||||
.set('dataToDelete', Map({}))
|
||||
.update('didDeleteData', (v) => !v);
|
||||
case FETCH_DATA_SUCCEEDED:
|
||||
return state.set('data', List(action.data));
|
||||
return state
|
||||
.set('data', List(action.data))
|
||||
.set('initialData', action.modifiedData)
|
||||
.set('modifiedData', action.modifiedData);
|
||||
case ON_CHANGE:
|
||||
return state
|
||||
.updateIn(['modifiedData', action.key], () => action.value)
|
||||
.set('showButtons', true);
|
||||
.updateIn(action.keys, () => action.value);
|
||||
case SET_DATA_TO_EDIT:
|
||||
return state.update('dataToEdit', () => action.dataToEdit);
|
||||
case SET_FORM:
|
||||
return state
|
||||
.set('formErrors', List([]))
|
||||
.set('initialData', action.form)
|
||||
.set('modifiedData', action.form);
|
||||
case SET_FORM_ERRORS:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.set('formErrors', List(action.formErrors));
|
||||
case SUBMIT_SUCCEEDED:
|
||||
return state
|
||||
.set('formErrors', List([]))
|
||||
.update('dataToEdit', () => '')
|
||||
.update('initialData', () => state.get('modifiedData'));
|
||||
case UNSET_DATA_TO_EDIT:
|
||||
return state
|
||||
.set('formErrors', List([]))
|
||||
.update('dataToEdit', () => '')
|
||||
.update('modifiedData', () => state.get('initialData'));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -8,11 +8,13 @@ import {
|
||||
deleteDataSucceeded,
|
||||
fetchDataSucceeded,
|
||||
setForm,
|
||||
submitSucceeded,
|
||||
} from './actions';
|
||||
|
||||
import {
|
||||
DELETE_DATA,
|
||||
FETCH_DATA,
|
||||
SUBMIT,
|
||||
} from './constants';
|
||||
|
||||
// TODO uncomment to test design providers and so on...
|
||||
@ -22,6 +24,7 @@ import {
|
||||
makeSelectAllData,
|
||||
makeSelectDataToDelete,
|
||||
makeSelectDeleteEndPoint,
|
||||
makeSelectModifiedData,
|
||||
} from './selectors';
|
||||
|
||||
export function* dataDelete() {
|
||||
@ -50,22 +53,36 @@ export function* dataFetch(action) {
|
||||
try {
|
||||
const response = yield call(request, `/users-permissions/${action.endPoint}`, { method: 'GET' });
|
||||
|
||||
yield put(fetchDataSucceeded(response[action.endPoint]));
|
||||
// To test other views
|
||||
// const response = data[action.endPoint];
|
||||
// yield put(fetchDataSucceeded(response));
|
||||
|
||||
yield put(setForm(action.endPoint));
|
||||
if (action.endPoint === 'advanced') {
|
||||
yield put(setForm(response));
|
||||
} else {
|
||||
const data = response[action.endPoint] || response;
|
||||
yield put(fetchDataSucceeded(data));
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
strapi.notification.error('users-permissions.notification.error.fetch');
|
||||
}
|
||||
}
|
||||
|
||||
export function* submitData(action) {
|
||||
try {
|
||||
const body = yield select(makeSelectModifiedData());
|
||||
const opts = { method: 'PUT', body };
|
||||
|
||||
yield call(request, `/users-permissions/${action.endPoint}`, opts, true);
|
||||
yield put(submitSucceeded());
|
||||
} catch(error) {
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
}
|
||||
// Individual exports for testing
|
||||
export function* defaultSaga() {
|
||||
const loadDataWatcher = yield fork(takeLatest, FETCH_DATA, dataFetch);
|
||||
|
||||
yield fork(takeLatest, DELETE_DATA, dataDelete);
|
||||
yield fork(takeLatest, SUBMIT, submitData);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
yield cancel(loadDataWatcher);
|
||||
}
|
||||
|
||||
@ -34,10 +34,15 @@ const makeSelectDeleteEndPoint = () => createSelector(
|
||||
(substate) => substate.get('deleteEndPoint'),
|
||||
);
|
||||
|
||||
export default selectHomePage;
|
||||
const makeSelectModifiedData = () => createSelector(
|
||||
selectHomePageDomain(),
|
||||
(substate) => substate.get('modifiedData').toJS(),
|
||||
);
|
||||
|
||||
export default selectHomePage;
|
||||
export {
|
||||
makeSelectAllData,
|
||||
makeSelectDataToDelete,
|
||||
makeSelectDeleteEndPoint,
|
||||
makeSelectModifiedData,
|
||||
};
|
||||
|
||||
@ -60,8 +60,10 @@
|
||||
"EditForm.inputSelect.durations.label": "Duration",
|
||||
"EditForm.inputSelect.durations.description": "Number of hours during the user can't subscribe.",
|
||||
|
||||
"EditForm.inputToggle.label": "One account per email addres",
|
||||
"EditForm.inputToggle.description": "Disallow the user to create multiple accounts using the same email address with different authentication providers.",
|
||||
"EditForm.inputToggle.label.email": "One account per email addres",
|
||||
"EditForm.inputToggle.label.sign-up": "Enable sign-up",
|
||||
"EditForm.inputToggle.description.email": "Disallow the user to create multiple accounts using the same email address with different authentication providers.",
|
||||
"EditForm.inputToggle.description.sign-up": "When disabled (OFF), the registration process is forbidden. No one can subscribe anymore no matter the used provider.",
|
||||
|
||||
"EditPage.cancel": "Cancel",
|
||||
"EditPage.submit": "Save",
|
||||
@ -123,9 +125,9 @@
|
||||
"Policies.header.hint": "Select the application's actions or the plugin's actions and click on the cog icon to display the bounded route",
|
||||
"Policies.header.title": "Advanced settings",
|
||||
|
||||
"Email.template.validation_email": "",
|
||||
"Email.template.reset_password": "",
|
||||
"Email.template.success_register": "",
|
||||
"Email.template.validation_email": "Email address validation",
|
||||
"Email.template.reset_password": "Reset password",
|
||||
"Email.template.success_register": "Successfull registration",
|
||||
|
||||
"Auth.advanced.allow_register": "",
|
||||
|
||||
@ -133,17 +135,39 @@
|
||||
"PopUpForm.button.save": "Save",
|
||||
"PopUpForm.header.add.providers": "Add New Provider",
|
||||
"PopUpForm.header.edit.email-templates": "Edit Email Templates",
|
||||
"PopUpForm.header.edit.providers": "Edit Provider",
|
||||
"PopUpForm.header.edit.providers": "Edit {provider} Provider",
|
||||
"PopUpForm.inputSelect.providers.label": "Choose the provider",
|
||||
"PopUpForm.inputToggle.providers.label": "Enable",
|
||||
"PopUpForm.inputToggle.providers.description": "If disabled, the users won't be able to use this provider.",
|
||||
"PopUpForm.inputText.shipperName.label": "Shipper name",
|
||||
"PopUpForm.inputEmail.shipperEmail.label": "Shipper email",
|
||||
"PopUpForm.inputEmail.responseEmail.label": "Response email",
|
||||
"PopUpForm.inputText.emailObject.label": "Object",
|
||||
"PopUpForm.inputText.emailObject.placeholder": "Please confirm your email address for %APP_NAME%",
|
||||
"PopUpForm.inputTextArea.message.label": "Message",
|
||||
"PopUpForm.inputTextArea.message.placeholder": "<p>Please click on this link to validate your account</p>",
|
||||
"PopUpForm.inputEmail.placeholder": "johndoe@gmail.com",
|
||||
"PopUpForm.inputText.shipperName.placeholder": "John Doe"
|
||||
"PopUpForm.Email.options.from.name.label": "Shipper name",
|
||||
"PopUpForm.Email.options.from.email.label": "Shipper email",
|
||||
"PopUpForm.Email.options.response_email.label": "Response email",
|
||||
"PopUpForm.Email.options.object.label": "Object",
|
||||
"PopUpForm.Email.options.message.label": "Message",
|
||||
"PopUpForm.Email.validation_email.options.object.placeholder": "Please confirm your email address for %APP_NAME%",
|
||||
"PopUpForm.Email.reset_password.options.object.placeholder": "Please confirm your email address for %APP_NAME%",
|
||||
"PopUpForm.Email.success_register.options.object.placeholder": "Please confirm your email address for %APP_NAME%",
|
||||
"PopUpForm.Email.validation_email.options.message.placeholder": "<p>Please click on this link to validate your account</p>",
|
||||
"PopUpForm.Email.reset_password.options.message.placeholder": "<p>Please click on this link to validate your account</p>",
|
||||
"PopUpForm.Email.success_register.options.message.placeholder": "<p>Please click on this link to validate your account</p>",
|
||||
"PopUpForm.Email.options.from.email.placeholder": "johndoe@gmail.com",
|
||||
"PopUpForm.Email.options.response_email.placeholder": "johndoe@gmail.com",
|
||||
"PopUpForm.Email.options.from.name.placeholder": "John Doe",
|
||||
"PopUpForm.Providers.enabled.label": "Enable",
|
||||
"PopUpForm.Providers.enabled.description": "If disabled, the users won't be able to use this provider.",
|
||||
"PopUpForm.Providers.key.label": "Client ID",
|
||||
"PopUpForm.Providers.key.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.secret.label": "Client Secret",
|
||||
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.redirectURL.front-end.label": "The redirect URL to your front-end app",
|
||||
|
||||
|
||||
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL": "The redirect URL to add in your Facebook application configurations",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL": "The redirect URL to add in your Google application configurations",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL": "The redirect URL to add in your GitHub application configurations",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL": "The redirect URL to add in your Linkedin application configurations",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL": "The redirect URL to add in your Twitter application configurations",
|
||||
|
||||
"PopUpForm.Providers.callback.placeholder": "TEXT",
|
||||
"PopUpForm.Email.email_templates.inputDescription": "Don't know to set variables",
|
||||
"PopUpForm.Email.link.documentation": "check out our documentation"
|
||||
}
|
||||
|
||||
@ -60,7 +60,9 @@
|
||||
"EditForm.inputSelect.durations.description": "Nombre d'heure pendant lesquelles un utilisateur ne peut souscrire.",
|
||||
|
||||
"EditForm.inputToggle.label": "Un compte par adresse email",
|
||||
"EditForm.inputToggle.description": "Interdire l'utilisateur de créer de multiple comptes avec la même adresse email avec des providers différents",
|
||||
"EditForm.inputToggle.label.sign-up": "Activer l'inscription",
|
||||
"EditForm.inputToggle.description.email": "Interdire l'utilisateur de créer de multiple comptes avec la même adresse email avec des providers différents",
|
||||
"EditForm.inputToggle.description.sign-up": "Quand l'inscription est désactivée (OFF), aucun utilisateur ne peut s'inscrire qu'importe le provider",
|
||||
|
||||
"EditPage.cancel": "Cancel",
|
||||
"EditPage.submit": "Sauvegarder",
|
||||
@ -123,27 +125,48 @@
|
||||
"Policies.header.hint": "Sélectionnez les actions de l'application ou d'un plugin et cliquer sur l'icon de paramètres pour voir les routes associées à cette action",
|
||||
"Policies.header.title": "Paramètres avancés",
|
||||
|
||||
"Email.template.validation_email": "",
|
||||
"Email.template.reset_password": "",
|
||||
"Email.template.success_register": "",
|
||||
"Email.template.validation_email": "Email de validation d'adresse",
|
||||
"Email.template.reset_password": "Modification de mot de passe",
|
||||
"Email.template.success_register": "Inscription réussie",
|
||||
|
||||
"Auth.advanced.allow_register": "",
|
||||
|
||||
"popUpForm.button.cancel": "Annuler",
|
||||
"popUpForm.button.save": "Sauvegarder",
|
||||
"popUpForm.header.add.providers": "Ajouter un Nouveau Provider",
|
||||
"popUpForm.header.edit.email-templates": "Editer Email Templates",
|
||||
"popUpForm.header.edit.providers": "Editer Le Provider",
|
||||
"popUpForm.inputSelect.providers.label": "Sélectionnez le provider",
|
||||
"popUpForm.inputToggle.providers.label": "Activer",
|
||||
"popUpForm.inputToggle.providers.description": "S'il est désactivé les utilisateurs ne pourront pas utiliser ce provider.",
|
||||
"popUpForm.inputText.shipperName.label": "Nom de l'envoyeur",
|
||||
"popUpForm.inputEmail.shipperEmail.label": "Email de l'envoyeur",
|
||||
"popUpForm.inputEmail.responseEmail.label": "Email de réponse",
|
||||
"popUpForm.inputText.emailObject.label": "Objet",
|
||||
"popUpForm.inputText.emailObject.placeholder": "Merci de confirmer votre adresse email pour %APP_NAME%",
|
||||
"popUpForm.inputTextArea.message.label": "Message",
|
||||
"popUpForm.inputTextArea.message.placeholder": "<p>Merci de cliquer sur ce lien pour valider votre compte</p>",
|
||||
"popUpForm.inputEmail.placeholder": "arthurdupont@gmail.com",
|
||||
"popUpForm.inputText.shipperName.placeholder": "Arthur Dupont"
|
||||
"PopUpForm.button.cancel": "Annuler",
|
||||
"PopUpForm.button.save": "Sauvegarder",
|
||||
"PopUpForm.header.add.providers": "Ajouter un Nouveau Provider",
|
||||
"PopUpForm.header.edit.email-templates": "Editer Email Templates",
|
||||
"PopUpForm.header.edit.providers": "Editer {provider} Provider",
|
||||
"PopUpForm.inputSelect.providers.label": "Sélectionnez le provider",
|
||||
"PopUpForm.Email.options.from.name.label": "Nom de l'envoyeur",
|
||||
"PopUpForm.Email.options.from.email.label": "Email de l'envoyeur",
|
||||
"PopUpForm.Email.options.response_email.label": "Email de réponse",
|
||||
"PopUpForm.Email.options.object.label": "Objet",
|
||||
"PopUpForm.Email.validation_email.options.object.placeholder": "Merci de confirmer votre adresse email pour %APP_NAME%",
|
||||
"PopUpForm.Email.success_register.options.object.placeholder": "Merci de confirmer votre adresse email pour %APP_NAME%",
|
||||
"PopUpForm.Email.reset_password.options.object.placeholder": "Merci de confirmer votre adresse email pour %APP_NAME%",
|
||||
"PopUpForm.Email.options.message.label": "Message",
|
||||
"PopUpForm.Email.validation_email.options.message.placeholder": "<p>Merci de cliquer sur ce lien pour valider votre compte</p>",
|
||||
"PopUpForm.Email.success_register.options.message.placeholder": "<p>Merci de cliquer sur ce lien pour valider votre compte</p>",
|
||||
"PopUpForm.Email.reset_password.options.message.placeholder": "<p>Merci de cliquer sur ce lien pour valider votre compte</p>",
|
||||
"PopUpForm.Email.options.from.email.placeholder": "arthurdupont@gmail.com",
|
||||
"PopUpForm.Email.options.response_email.placeholder": "arthurdupont@gmail.com",
|
||||
"PopUpForm.Email.options.from.name.placeholder": "Arthur Dupont",
|
||||
"PopUpForm.Providers.enabled.label": "Activer",
|
||||
"PopUpForm.Providers.enabled.description": "S'il est désactivé les utilisateurs ne pourront pas utiliser ce provider.",
|
||||
"PopUpForm.Providers.key.label": "Client ID",
|
||||
"PopUpForm.Providers.key.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.secret.label": "Client Secret",
|
||||
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
||||
|
||||
"PopUpForm.Providers.redirectURL.front-end.label": "L'URL de redirection de votre app front-end",
|
||||
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL": "L'URL de redirection à ajouter dans les configurations Facebook de votre application",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL": "L'URL de redirection à ajouter dans les configurations Google de votre application",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL": "L'URL de redirection à ajouter dans les configurations GitHub de votre application",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL": "L'URL de redirection à ajouter dans les configurations Linkedin de votre application",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL": "L'URL de redirection à ajouter dans les configurations Twitter de votre application",
|
||||
|
||||
"PopUpForm.Providers.callback.placeholder": "TEXT",
|
||||
"PopUpForm.Email.email_templates.inputDescription": "Regardez la documentation des variables",
|
||||
"PopUpForm.Email.link.documentation": "afin de templeter vos emails"
|
||||
}
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"advanced": {
|
||||
"unique_email": true,
|
||||
"allow_register": true
|
||||
}
|
||||
}
|
||||
@ -31,11 +31,13 @@ module.exports = cb => {
|
||||
if (!_.get(strapi.plugins['users-permissions'], 'config.grant')) {
|
||||
try {
|
||||
const grant = {
|
||||
local: {
|
||||
enabled: true
|
||||
email: {
|
||||
enabled: true,
|
||||
icon: 'envelope'
|
||||
},
|
||||
facebook: {
|
||||
enabled: false,
|
||||
icon: 'facebook-official',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/facebook/callback',
|
||||
@ -43,6 +45,7 @@ module.exports = cb => {
|
||||
},
|
||||
google: {
|
||||
enabled: false,
|
||||
icon: 'google',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/google/callback',
|
||||
@ -50,9 +53,10 @@ module.exports = cb => {
|
||||
},
|
||||
github: {
|
||||
enabled: false,
|
||||
icon: 'github',
|
||||
key: '',
|
||||
secret: '',
|
||||
redirect_uri: '/auth/google/callback',
|
||||
redirect_uri: '/auth/github/callback',
|
||||
scope: [
|
||||
'user',
|
||||
'user:email'
|
||||
@ -60,6 +64,7 @@ module.exports = cb => {
|
||||
},
|
||||
twitter: {
|
||||
enabled: false,
|
||||
icon: 'twitter',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/twitter/callback'
|
||||
@ -84,10 +89,10 @@ module.exports = cb => {
|
||||
icon: 'envelope',
|
||||
options: {
|
||||
from: {
|
||||
email: '',
|
||||
name: ''
|
||||
name: 'Administration Panel',
|
||||
email: 'no-reply@strapi.io'
|
||||
},
|
||||
respond: '',
|
||||
response_email: '',
|
||||
object: '',
|
||||
message: ''
|
||||
}
|
||||
@ -97,10 +102,10 @@ module.exports = cb => {
|
||||
icon: 'refresh',
|
||||
options: {
|
||||
from: {
|
||||
email: '',
|
||||
name: ''
|
||||
name: 'Administration Panel',
|
||||
email: 'no-reply@strapi.io'
|
||||
},
|
||||
respond: '',
|
||||
response_email: '',
|
||||
object: 'Reset password 🔑 ',
|
||||
message: `<p>We heard that you lost your password. Sorry about that!</p>
|
||||
|
||||
@ -116,10 +121,10 @@ module.exports = cb => {
|
||||
icon: 'check',
|
||||
options: {
|
||||
from: {
|
||||
email: '',
|
||||
name: ''
|
||||
name: 'Administration Panel',
|
||||
email: 'no-reply@strapi.io'
|
||||
},
|
||||
respond: '',
|
||||
response_email: '',
|
||||
object: '',
|
||||
message: ''
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/email-template",
|
||||
"path": "/email-templates",
|
||||
"handler": "UsersPermissions.getEmailTemplate",
|
||||
"config": {
|
||||
"policies": []
|
||||
@ -74,7 +74,7 @@
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/email-template",
|
||||
"path": "/email-templates",
|
||||
"handler": "UsersPermissions.updateEmailTemplate",
|
||||
"config": {
|
||||
"policies": []
|
||||
@ -96,6 +96,23 @@
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/providers",
|
||||
"handler": "UsersPermissions.getProviders",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/providers",
|
||||
"handler": "UsersPermissions.updateProviders",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
|
||||
@ -17,7 +17,7 @@ module.exports = {
|
||||
const params = ctx.request.body;
|
||||
|
||||
if (provider === 'local') {
|
||||
if (!_.get(strapi.plugins['users-permissions'].config.grant[provider], 'enabled') && !ctx.request.admin) {
|
||||
if (!_.get(strapi.plugins['users-permissions'].config.grant['email'], 'enabled') && !ctx.request.admin) {
|
||||
return ctx.badRequest(null, 'This provider is disabled.');
|
||||
}
|
||||
|
||||
@ -71,9 +71,9 @@ module.exports = {
|
||||
}
|
||||
} else {
|
||||
// Connect the user thanks to the third-party provider.
|
||||
const [user, error] = await strapi.plugins['users-permissions'].services.providers.connect(provider, ctx.query);
|
||||
|
||||
if (error) {
|
||||
try {
|
||||
const [user, error] = await strapi.plugins['users-permissions'].services.providers.connect(provider, ctx.query);
|
||||
} catch([user, error]) {
|
||||
return ctx.badRequest(null, (error === 'array') ? (ctx.request.admin ? error[0] : error[1]) : error);
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ module.exports = {
|
||||
await strapi.plugins['email'].services.email.send({
|
||||
to: user.email,
|
||||
from: (settings.from.email || settings.from.name) ? `"${settings.from.name}" <${settings.from.email}>` : undefined,
|
||||
replyTo: settings.respond,
|
||||
replyTo: settings.response_email,
|
||||
subject: settings.object,
|
||||
text: settings.message,
|
||||
html: settings.message
|
||||
|
||||
@ -179,13 +179,15 @@ module.exports = {
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
|
||||
}
|
||||
|
||||
strapi.plugins['users-permissions'].config.email = ctx.request.body;
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'email.json'), JSON.stringify({
|
||||
email: strapi.plugins['users-permissions'].config.email
|
||||
email: ctx.request.body
|
||||
}, null, 2), 'utf8');
|
||||
|
||||
return ctx.send({ ok: true });
|
||||
ctx.send({ ok: true });
|
||||
|
||||
strapi.reload();
|
||||
},
|
||||
|
||||
getAdvancedSettings: async (ctx) => {
|
||||
@ -197,12 +199,35 @@ module.exports = {
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
|
||||
}
|
||||
|
||||
strapi.plugins['users-permissions'].config.advanced = ctx.request.body;
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'advanced.json'), JSON.stringify({
|
||||
email: strapi.plugins['users-permissions'].config.advanced
|
||||
advanced: ctx.request.body
|
||||
}, null, 2), 'utf8');
|
||||
|
||||
return ctx.send({ ok: true });
|
||||
ctx.send({ ok: true });
|
||||
|
||||
strapi.reload();
|
||||
},
|
||||
|
||||
getProviders: async (ctx) => {
|
||||
ctx.send(strapi.plugins['users-permissions'].config.grant);
|
||||
},
|
||||
|
||||
updateProviders: async (ctx) => {
|
||||
if (_.isEmpty(ctx.request.body)) {
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
|
||||
}
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'grant.json'), JSON.stringify({
|
||||
grant: ctx.request.body
|
||||
}, null, 2), 'utf8');
|
||||
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
strapi.reload();
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
# Templating emails
|
||||
|
||||
Documentation in progress....
|
||||
@ -63,8 +63,8 @@ exports.connect = (provider, query) => {
|
||||
return reject([{
|
||||
message: 'Email was not available.'
|
||||
}, null]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await strapi.query('user', 'users-permissions').findOne({email: profile.email});
|
||||
|
||||
@ -83,7 +83,8 @@ exports.connect = (provider, query) => {
|
||||
if (!user || _.get(user, 'provider') !== provider) {
|
||||
// Create the new user.
|
||||
const params = _.assign(profile, {
|
||||
provider: provider
|
||||
provider: provider,
|
||||
role: '1'
|
||||
});
|
||||
|
||||
const createdUser = await strapi.query('user', 'users-permissions').create(params);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user