mirror of
https://github.com/strapi/strapi.git
synced 2025-12-24 05:34:33 +00:00
Merge branch 'master' into translation/fr
This commit is contained in:
commit
1dbbea458d
1
.gitignore
vendored
1
.gitignore
vendored
@ -78,6 +78,7 @@ $RECYCLE.BIN/
|
||||
*#
|
||||
.idea
|
||||
nbproject
|
||||
.vscode/
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -59,7 +59,8 @@ $.ajax({
|
||||
|
||||
Thanks to [Grant](https://github.com/simov/grant) and [Purest](https://github.com/simov/purest), you can easily use OAuth and OAuth2
|
||||
providers to enable authentication in your application. By default,
|
||||
Strapi comes with four providers:
|
||||
Strapi comes with the following providers:
|
||||
- [Discord](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/discord_setup.md)
|
||||
- [Facebook](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/fb_setup.md)
|
||||
- [Google](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/google_setup.md)
|
||||
- [Github](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/github_setup.md)
|
||||
|
||||
@ -11,7 +11,7 @@ There are several ways to create a policy.
|
||||
**Path —** `./config/policies/isAuthenticated.js`.
|
||||
```js
|
||||
module.exports = async (ctx, next) => {
|
||||
if (ctx.session.isAuthenticated === true) {
|
||||
if (ctx.state.user) {
|
||||
// Go to next policy or will reach the controller's action.
|
||||
return await next();
|
||||
}
|
||||
@ -87,7 +87,7 @@ The scoped policies can only be associated to the routes defined in the API wher
|
||||
**Path —** `./api/car/config/policies/isAdmin.js`.
|
||||
```js
|
||||
module.exports = async (ctx, next) => {
|
||||
if (ctx.session.user.role === 'administrator') {
|
||||
if (ctx.state.user.role.name === 'Administrator') {
|
||||
// Go to next policy or will reach the controller's action.
|
||||
return await next();
|
||||
}
|
||||
|
||||
@ -149,6 +149,8 @@
|
||||
"Users & Permissions": "Usuários & Permissões",
|
||||
"Content Manager": "Gestão de conteúdo",
|
||||
"Content Type Builder": "Construtor de Conteúdo",
|
||||
"Files Upload": "Enviar arquivos",
|
||||
"Roles & Permissions": "Papéis e permissões",
|
||||
"Settings Manager": "Gerenciador de configurações",
|
||||
"Email": "E-mail",
|
||||
"Password": "Senha",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const exec = require('child_process').execSync;
|
||||
const exec = require('child_process').spawnSync;
|
||||
const _ = require('lodash');
|
||||
|
||||
/**
|
||||
@ -53,8 +53,7 @@ module.exports = {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
strapi.log.info(`Installing ${plugin}...`);
|
||||
|
||||
exec(`node "${strapiBin}" install ${plugin} ${port === '4000' ? '--dev' : ''}`);
|
||||
exec('node', [strapiBin, 'install', plugin, (port === '4000') ? '--dev' : '']);
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
@ -87,7 +86,7 @@ module.exports = {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
strapi.log.info(`Uninstalling ${plugin}...`);
|
||||
exec(`node "${strapiBin}" uninstall ${plugin}`);
|
||||
exec('node', [strapiBin, 'uninstall', plugin]);
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
|
||||
@ -51,4 +51,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-email-amazon-ses",
|
||||
"version": "3.0.0-alpha.13",
|
||||
"version": "3.0.0-alpha.13.0.1",
|
||||
"description": "Amazon SES provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -42,4 +42,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -42,4 +42,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -42,4 +42,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -41,4 +41,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -42,4 +42,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -43,4 +43,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -115,4 +115,4 @@
|
||||
"webpack-hot-middleware": "^2.18.2",
|
||||
"whatwg-fetch": "^2.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,4 +43,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -45,4 +45,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -44,4 +44,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -41,4 +41,4 @@
|
||||
"babel-eslint": "^8.2.3",
|
||||
"prettier": "^1.12.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,4 +43,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="8px" height="8px" viewBox="0 0 8 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Icon grab</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Pages" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Content-Manager---Settings-view---Single" transform="translate(-335.000000, -698.000000)" fill="#B3B5B9">
|
||||
<g id="Container" transform="translate(261.000000, 84.000000)">
|
||||
<g id="Forms" transform="translate(3.000000, 77.000000)">
|
||||
<g id="Settings">
|
||||
<g id="Attributes" transform="translate(4.000000, 456.000000)">
|
||||
<g id="Order-attributes" transform="translate(0.000000, 23.000000)">
|
||||
<g id="Link" transform="translate(0.000000, 19.000000)">
|
||||
<g id="Icon-grab" transform="translate(67.000000, 39.000000)">
|
||||
<rect id="Rectangle-4" x="0" y="0" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="3" y="0" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="6" y="0" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="0" y="3" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="3" y="3" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="6" y="3" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="0" y="6" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="3" y="6" width="2" height="2"></rect>
|
||||
<rect id="Rectangle-4" x="6" y="6" width="2" height="2"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Icon remove</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Pages" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Content-Manager---List-view" transform="translate(-279.000000, -165.000000)">
|
||||
<g id="Container" transform="translate(234.000000, 0.000000)">
|
||||
<g id="Add-filters" transform="translate(0.000000, 60.000000)">
|
||||
<g id="Icon-remove" transform="translate(45.000000, 105.000000)">
|
||||
<rect id="Rectangle-12" stroke="#E3E9F3" x="0.5" y="0.5" width="19" height="19" rx="9.5"></rect>
|
||||
<path d="M6,10 L14,10" id="Line-4" stroke="#007EFF" stroke-width="2" stroke-linecap="round"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get, map } from 'lodash';
|
||||
|
||||
@ -26,9 +25,6 @@ const filterRelationsUpload = (data) => Object.keys(data).reduce((acc, current)
|
||||
function EditRelations(props) {
|
||||
return (
|
||||
<div className={styles.editFormRelations}>
|
||||
<FormattedMessage id="content-manager.EditRelations.title">
|
||||
{(message) => <h3>{message}</h3>}
|
||||
</FormattedMessage>
|
||||
{map(filterRelationsUpload(props.schema.relations), (relation, key) => {
|
||||
if (relation.nature.toLowerCase().includes('morph') && relation[key]) return '';
|
||||
|
||||
@ -43,6 +39,7 @@ function EditRelations(props) {
|
||||
schema={props.schema}
|
||||
setRecordAttribute={props.changeData}
|
||||
location={props.location}
|
||||
onRedirect={props.onRedirect}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -59,6 +56,7 @@ EditRelations.propTypes = {
|
||||
changeData: PropTypes.func.isRequired,
|
||||
currentModelName: PropTypes.string.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
onRedirect: PropTypes.func.isRequired,
|
||||
record: PropTypes.object,
|
||||
schema: PropTypes.object,
|
||||
};
|
||||
|
||||
@ -1,13 +1,3 @@
|
||||
.editFormRelations { /* stylelint-disable */
|
||||
h3{
|
||||
height: 41px;
|
||||
margin: 0 -25px 14px;
|
||||
padding: 0 25px;
|
||||
background: #F3F3F3;
|
||||
line-height: 41px;
|
||||
border-radius: 2px 2px 0 0;
|
||||
letter-spacing: 0.03rem;
|
||||
font-size: 1.3rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
padding-top: 19px;
|
||||
}
|
||||
|
||||
@ -6,32 +6,87 @@
|
||||
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { SortableContainer, SortableElement, arrayMove } from 'react-sortable-hoc';
|
||||
import PropTypes from 'prop-types';
|
||||
import 'react-select/dist/react-select.css';
|
||||
import { cloneDeep, isArray, isNull, isUndefined, get, findIndex, includes } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
import { cloneDeep, isArray, isNull, isUndefined, get, findIndex, includes, isEmpty } from 'lodash';
|
||||
|
||||
// Utils.
|
||||
import request from 'utils/request';
|
||||
import templateObject from 'utils/templateObject';
|
||||
|
||||
// CSS.
|
||||
import 'react-select/dist/react-select.css';
|
||||
|
||||
// Icons.
|
||||
import IconRemove from '../../assets/images/icon_remove.svg';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
class SelectMany extends React.Component {
|
||||
// eslint-disable-line react/prefer-stateless-function
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const SortableItem = SortableElement(({idx, onRemove, item, onClick}) => {
|
||||
return (
|
||||
<li className={styles.sortableListItem}>
|
||||
<div>
|
||||
<div className={styles.dragHandle}><span></span></div>
|
||||
<FormattedMessage id='content-manager.containers.Edit.clickToJump'>
|
||||
{title => (
|
||||
<span
|
||||
className='sortable-item--value'
|
||||
onClick={() => onClick(item)}
|
||||
title={title}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
|
||||
</div>
|
||||
<div className={styles.sortableListItemActions}>
|
||||
<img src={IconRemove} alt="Remove Icon" onClick={() => onRemove(idx)} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
options: [],
|
||||
toSkip: 0,
|
||||
};
|
||||
}
|
||||
const SortableList = SortableContainer(({items, onRemove, onClick}) => {
|
||||
const shadowList = (items.length > 4 ? <div className={styles.sortableListLong}></div> : '');
|
||||
|
||||
return (
|
||||
<div className={cn(styles.sortableList)}>
|
||||
<ul>
|
||||
{items.map((item, index) => (
|
||||
<SortableItem key={`item-${index}`} index={index} idx={index} item={item} onRemove={onRemove} onClick={onClick} />
|
||||
))}
|
||||
</ul>
|
||||
{shadowList}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
class SelectMany extends React.PureComponent {
|
||||
state = {
|
||||
isLoading: true,
|
||||
options: [],
|
||||
toSkip: 0,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.getOptions('');
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (isEmpty(prevProps.record) && !isEmpty(this.props.record)) {
|
||||
const values = (get(this.props.record, this.props.relation.alias) || [])
|
||||
.map(el => (el.id || el._id));
|
||||
|
||||
const options = this.state.options.filter(el => {
|
||||
return !values.includes(el.value.id || el.value._id);
|
||||
});
|
||||
|
||||
this.state.options = options;
|
||||
}
|
||||
|
||||
if (prevState.toSkip !== this.state.toSkip) {
|
||||
this.getOptions('');
|
||||
}
|
||||
@ -92,15 +147,23 @@ class SelectMany extends React.Component {
|
||||
};
|
||||
|
||||
handleChange = value => {
|
||||
const filteredValue = value.filter(
|
||||
(data, index) => findIndex(value, o => o.value.id === data.value.id) === index
|
||||
);
|
||||
const values = get(this.props.record, this.props.relation.alias) || [];
|
||||
|
||||
const target = {
|
||||
name: `record.${this.props.relation.alias}`,
|
||||
type: 'select',
|
||||
value: filteredValue,
|
||||
value: [...values, value.value],
|
||||
};
|
||||
|
||||
// Remove new added value from available option;
|
||||
this.state.options = this.state.options.filter(el => {
|
||||
if (el.value._id || el.value.id === value.value.id || value.value._id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.props.setRecordAttribute({ target });
|
||||
};
|
||||
|
||||
@ -121,6 +184,44 @@ class SelectMany extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleSortEnd = ({oldIndex, newIndex}) => {
|
||||
const values = get(this.props.record, this.props.relation.alias);
|
||||
const target = {
|
||||
name: `record.${this.props.relation.alias}`,
|
||||
type: 'select',
|
||||
value: arrayMove(values, oldIndex, newIndex),
|
||||
};
|
||||
|
||||
this.props.setRecordAttribute({ target });
|
||||
};
|
||||
|
||||
handleRemove = (index) => {
|
||||
const values = get(this.props.record, this.props.relation.alias);
|
||||
const target = {
|
||||
name: `record.${this.props.relation.alias}`,
|
||||
type: 'select',
|
||||
value: values.filter( (item, idx) => idx !== index),
|
||||
};
|
||||
|
||||
// Add removed value from available option;
|
||||
this.state.options.push({
|
||||
value: values[index],
|
||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, values[index])
|
||||
.mainField,
|
||||
});
|
||||
|
||||
this.props.setRecordAttribute({ target });
|
||||
}
|
||||
|
||||
// Redirect to the edit page
|
||||
handleClick = (item = {}) => {
|
||||
this.props.onRedirect({
|
||||
model: this.props.relation.collection || this.props.relation.model,
|
||||
id: item.value.id || item.value._id,
|
||||
source: this.props.relation.plugin,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const description = this.props.relation.description ? (
|
||||
<p>{this.props.relation.description}</p>
|
||||
@ -128,11 +229,12 @@ class SelectMany extends React.Component {
|
||||
''
|
||||
);
|
||||
|
||||
const value = get(this.props.record, this.props.relation.alias);
|
||||
const value = get(this.props.record, this.props.relation.alias) || [];
|
||||
|
||||
/* eslint-disable jsx-a11y/label-has-for */
|
||||
return (
|
||||
<div className={`form-group ${styles.selectMany}`}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||
<div className={`form-group ${styles.selectMany} ${value.length > 4 && styles.selectManyUpdate}`}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias} <span>({value.length})</span></label>
|
||||
{description}
|
||||
<Select
|
||||
onChange={this.handleChange}
|
||||
@ -140,10 +242,10 @@ class SelectMany extends React.Component {
|
||||
id={this.props.relation.alias}
|
||||
isLoading={this.state.isLoading}
|
||||
onMenuScrollToBottom={this.handleBottomScroll}
|
||||
onInputChange={this.handleInputChange}
|
||||
onSelectResetsInput={false}
|
||||
multi
|
||||
value={
|
||||
placeholder={<FormattedMessage id='content-manager.containers.Edit.addAnItem' />}
|
||||
/>
|
||||
<SortableList
|
||||
items={
|
||||
isNull(value) || isUndefined(value) || value.size === 0
|
||||
? null
|
||||
: value.map(item => {
|
||||
@ -159,6 +261,10 @@ class SelectMany extends React.Component {
|
||||
}
|
||||
})
|
||||
}
|
||||
onSortEnd={this.handleSortEnd}
|
||||
onRemove={this.handleRemove}
|
||||
distance={1}
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -167,6 +273,7 @@ class SelectMany extends React.Component {
|
||||
}
|
||||
|
||||
SelectMany.propTypes = {
|
||||
onRedirect: PropTypes.func.isRequired,
|
||||
record: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
|
||||
relation: PropTypes.object.isRequired,
|
||||
setRecordAttribute: PropTypes.func.isRequired,
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
.selectMany { /* stylelint-disable */
|
||||
padding-bottom: 19px;
|
||||
margin-bottom: 0px;
|
||||
overflow-x: hidden;
|
||||
|
||||
label{
|
||||
font-size: 1.3rem;
|
||||
font-weight: 500;
|
||||
text-transform: capitalize;
|
||||
margin-top: 3px;
|
||||
|
||||
> span {
|
||||
font-weight: 400;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
label + div{
|
||||
margin: 5px 0 26px;
|
||||
margin: 3px 0 26px;
|
||||
|
||||
&:focus{
|
||||
outline: none;
|
||||
@ -25,3 +34,145 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selectManyUpdate{
|
||||
padding-bottom: 18px !important;
|
||||
}
|
||||
|
||||
.sortableList {
|
||||
max-height: 110px;
|
||||
|
||||
> ul {
|
||||
margin: -21px -20px 0;
|
||||
padding: 0 20px !important;
|
||||
list-style: none !important;
|
||||
overflow: scroll;
|
||||
max-height: 110px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.sortableListLong {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: -5px;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: calc(100% + 10px);
|
||||
height: 1px;
|
||||
margin-bottom: -25px;
|
||||
box-shadow: 0px -2px 4px 0px rgba(227, 233, 243, .5);
|
||||
}
|
||||
}
|
||||
|
||||
.sortableListItem {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: space-between;
|
||||
height: 27px;
|
||||
|
||||
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
|
||||
&:active{
|
||||
.dragHandle{
|
||||
cursor: pointer;
|
||||
|
||||
> span {
|
||||
background: #AED4FB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dragHandle{
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
margin-top: -1px;
|
||||
|
||||
> span {
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 1px;
|
||||
padding: 0px !important;
|
||||
background: #B3B5B9;
|
||||
overflow: visible !important;
|
||||
transition: background .25s ease-out;
|
||||
|
||||
&:before, &:after{
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 1px;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
&:before{
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:after{
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> div {
|
||||
span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:first-of-type{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: color .25s ease-out;
|
||||
|
||||
&:hover{
|
||||
.dragHandle{
|
||||
> span {
|
||||
background: #007EFF;
|
||||
}
|
||||
}
|
||||
|
||||
color: #007EFF;
|
||||
}
|
||||
|
||||
span {
|
||||
&:last-of-type{
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-of-type{
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
line-height: 27px;
|
||||
text-align: right;
|
||||
padding-right: 0px;
|
||||
|
||||
img{
|
||||
display: inline-block;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import 'react-select/dist/react-select.css';
|
||||
import { cloneDeep, map, includes, isArray, isNull, isUndefined, isFunction, get, findIndex } from 'lodash';
|
||||
@ -106,6 +107,15 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
||||
});
|
||||
}
|
||||
|
||||
// Redirect to the edit page
|
||||
handleClick = (item = {}) => {
|
||||
this.props.onRedirect({
|
||||
model: this.props.relation.collection || this.props.relation.model,
|
||||
id: item.value.id || item.value._id,
|
||||
source: this.props.relation.plugin,
|
||||
});
|
||||
}
|
||||
|
||||
handleInputChange = (value) => {
|
||||
const clonedOptions = this.state.options;
|
||||
const filteredValues = clonedOptions.filter(data => includes(data.label, value));
|
||||
@ -121,11 +131,25 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
||||
: '';
|
||||
|
||||
const value = get(this.props.record, this.props.relation.alias);
|
||||
const excludeModel = ['role', 'permission', 'file'].includes(this.props.relation.model || this.props.relation.collection); // Temporary.
|
||||
const entryLink = (isNull(value) || isUndefined(value) || excludeModel ?
|
||||
'' :
|
||||
(
|
||||
<FormattedMessage id='content-manager.containers.Edit.clickToJump'>
|
||||
{title => (
|
||||
<a onClick={() => this.handleClick({value})} title={title}><FormattedMessage id='content-manager.containers.Edit.seeDetails' /></a>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
)
|
||||
);
|
||||
|
||||
/* eslint-disable jsx-a11y/label-has-for */
|
||||
return (
|
||||
<div className={`form-group ${styles.selectOne}`}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||
<nav className={styles.headline}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||
{entryLink}
|
||||
</nav>
|
||||
{description}
|
||||
<Select
|
||||
onChange={this.handleChange}
|
||||
@ -140,6 +164,7 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, isFunction(value.toJS) ? value.toJS() : value).mainField || (isFunction(value.toJS) ? get(value.toJS(), 'id') : get(value, 'id')),
|
||||
}}
|
||||
/>
|
||||
|
||||
</div>
|
||||
);
|
||||
/* eslint-disable jsx-a11y/label-has-for */
|
||||
@ -147,6 +172,7 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
||||
}
|
||||
|
||||
SelectOne.propTypes = {
|
||||
onRedirect: PropTypes.func.isRequired,
|
||||
record: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
||||
PropTypes.bool,
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
.selectOne { /* stylelint-disable */
|
||||
position: relative;
|
||||
|
||||
label{
|
||||
font-size: 1.3rem;
|
||||
font-weight: 500;
|
||||
@ -6,7 +8,7 @@
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
label + div{
|
||||
nav + div{
|
||||
height: 34px;
|
||||
margin: 3px 0 26px;
|
||||
|
||||
@ -28,3 +30,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.headline{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
a{
|
||||
color: #007EFF !important;
|
||||
font-size: 1.3rem;
|
||||
padding-top: 3px;
|
||||
|
||||
&:hover{
|
||||
text-decoration: underline !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ export function initModelProps(modelName, isCreating, source, attributes) {
|
||||
const record = Object.keys(attributes).reduce((acc, current) => {
|
||||
if (attributes[current].default) {
|
||||
acc[current] = attributes[current].default;
|
||||
} else if (attributes[current].type === 'json') {
|
||||
acc[current] = {};
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import injectSaga from 'utils/injectSaga';
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
import { bindLayout } from 'utils/bindLayout';
|
||||
import inputValidations from 'utils/inputsValidations';
|
||||
import { generateRedirectURI } from 'containers/ListPage/utils';
|
||||
|
||||
import { checkFormValidity } from 'utils/formValidations';
|
||||
|
||||
@ -57,35 +58,15 @@ export class EditPage extends React.Component {
|
||||
state = { showWarning: false };
|
||||
|
||||
componentDidMount() {
|
||||
this.props.initModelProps(this.getModelName(), this.isCreating(), this.getSource(), this.getModelAttributes());
|
||||
|
||||
if (!this.isCreating()) {
|
||||
const mainField = get(this.getModel(), 'info.mainField') || this.getModel().primaryKey;
|
||||
this.props.getData(this.props.match.params.id, this.getSource(), mainField);
|
||||
} else {
|
||||
this.props.getLayout(this.getSource());
|
||||
}
|
||||
|
||||
// Get all relations made with the upload plugin
|
||||
const fileRelations = Object.keys(get(this.getSchema(), 'relations', {})).reduce((acc, current) => {
|
||||
const association = get(this.getSchema(), ['relations', current], {});
|
||||
|
||||
if (association.plugin === 'upload' && association[association.type] === 'file') {
|
||||
const relation = {
|
||||
name: current,
|
||||
multiple: association.nature === 'manyToManyMorph',
|
||||
};
|
||||
|
||||
acc.push(relation);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// Update the reducer so we can use it to create the appropriate FormData in the saga
|
||||
this.props.setFileRelations(fileRelations);
|
||||
this.initComponent(this.props);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.location.pathname !== this.props.location.pathname) {
|
||||
this.props.resetProps();
|
||||
this.initComponent(this.props);
|
||||
}
|
||||
|
||||
if (prevProps.editPage.submitSuccess !== this.props.editPage.submitSuccess) {
|
||||
if (!isEmpty(this.props.location.search) && includes(this.props.location.search, '?redirectUrl')) {
|
||||
const redirectUrl = this.props.location.search.split('?redirectUrl=')[1];
|
||||
@ -168,6 +149,38 @@ export class EditPage extends React.Component {
|
||||
*/
|
||||
getSource = () => getQueryParameters(this.props.location.search, 'source');
|
||||
|
||||
/**
|
||||
* Initialize component
|
||||
*/
|
||||
initComponent = (props) => {
|
||||
this.props.initModelProps(this.getModelName(), this.isCreating(), this.getSource(), this.getModelAttributes());
|
||||
|
||||
if (!this.isCreating()) {
|
||||
const mainField = get(this.getModel(), 'info.mainField') || this.getModel().primaryKey;
|
||||
this.props.getData(props.match.params.id, this.getSource(), mainField);
|
||||
} else {
|
||||
this.props.getLayout(this.getSource());
|
||||
}
|
||||
|
||||
// Get all relations made with the upload plugin
|
||||
const fileRelations = Object.keys(get(this.getSchema(), 'relations', {})).reduce((acc, current) => {
|
||||
const association = get(this.getSchema(), ['relations', current], {});
|
||||
|
||||
if (association.plugin === 'upload' && association[association.type] === 'file') {
|
||||
const relation = {
|
||||
name: current,
|
||||
multiple: association.nature === 'manyToManyMorph',
|
||||
};
|
||||
|
||||
acc.push(relation);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// Update the reducer so we can use it to create the appropriate FormData in the saga
|
||||
this.props.setFileRelations(fileRelations);
|
||||
}
|
||||
|
||||
handleBlur = ({ target }) => {
|
||||
const defaultValue = get(this.getModelAttribute(target.name), 'default');
|
||||
|
||||
@ -212,6 +225,27 @@ export class EditPage extends React.Component {
|
||||
this.props.changeData({ target });
|
||||
}
|
||||
|
||||
handleRedirect = ({ model, id, source = 'content-manager'}) => {
|
||||
/* eslint-disable */
|
||||
switch (model) {
|
||||
case 'permission':
|
||||
case 'role':
|
||||
case 'file':
|
||||
// Exclude special models which are handled by plugins.
|
||||
if (source !== 'content-manager') {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
const pathname = `${this.props.match.path.replace(':slug', model).replace(':id', id)}`;
|
||||
|
||||
this.props.history.push({
|
||||
pathname,
|
||||
search: `?source=${source}&redirectURI=${generateRedirectURI({ model, search: `?source=${source}` })}`,
|
||||
});
|
||||
}
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const formErrors = checkFormValidity(this.generateFormFromRecord(), this.props.editPage.formValidations);
|
||||
@ -330,6 +364,7 @@ export class EditPage extends React.Component {
|
||||
changeData={this.props.changeData}
|
||||
record={editPage.record}
|
||||
schema={this.getSchema()}
|
||||
onRedirect={this.handleRedirect}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -87,9 +87,10 @@ export function* submit() {
|
||||
// Show button loader
|
||||
yield put(setLoader());
|
||||
const recordCleaned = Object.keys(record).reduce((acc, current) => {
|
||||
const attrType = source !== 'content-manager' ? get(schema, ['plugins', source, currentModelName, 'fields', current, 'type'], null) : get(schema, [currentModelName, 'fields', current, 'type'], null);
|
||||
const attrType = source !== 'content-manager' ? get(schema, ['models', 'plugins', source, currentModelName, 'fields', current, 'type'], null) : get(schema, ['models', currentModelName, 'fields', current, 'type'], null);
|
||||
const cleanedData = attrType === 'json' ? record[current] : cleanData(record[current], 'value', 'id');
|
||||
|
||||
|
||||
if (isString(cleanedData) || isNumber(cleanedData)) {
|
||||
acc.append(current, cleanedData);
|
||||
} else if (findIndex(fileRelations, ['name', current]) !== -1) {
|
||||
@ -114,6 +115,11 @@ export function* submit() {
|
||||
return acc;
|
||||
}, new FormData());
|
||||
|
||||
// Helper to visualize FormData
|
||||
// for(var pair of recordCleaned.entries()) {
|
||||
// console.log(pair[0]+ ', '+ pair[1]);
|
||||
// }
|
||||
|
||||
const id = isCreating ? '' : record.id || record._id;
|
||||
const params = { source };
|
||||
// Change the request helper default headers so we can pass a FormData
|
||||
|
||||
@ -62,6 +62,7 @@ import {
|
||||
generateFiltersFromSearch,
|
||||
generateSearchFromFilters,
|
||||
generateSearchFromParams,
|
||||
generateRedirectURI,
|
||||
} from './utils';
|
||||
|
||||
import styles from './styles.scss';
|
||||
@ -177,9 +178,7 @@ export class ListPage extends React.Component {
|
||||
* Generate the redirect URI when editing an entry
|
||||
* @type {String}
|
||||
*/
|
||||
generateRedirectURI = () => (
|
||||
`?redirectUrl=/plugins/content-manager/${this.getCurrentModelName().toLowerCase()}${this.generateSearch()}`
|
||||
);
|
||||
generateRedirectURI = generateRedirectURI.bind(this);
|
||||
|
||||
generateSearch = () => {
|
||||
const {
|
||||
|
||||
@ -50,8 +50,17 @@ const generateSearchFromParams = params =>
|
||||
return acc;
|
||||
}, '');
|
||||
|
||||
/**
|
||||
* Generate the redirect URI when editing an entry
|
||||
* @type {String}
|
||||
*/
|
||||
const generateRedirectURI = function ({ model, search } = {}) {
|
||||
return `?redirectUrl=/plugins/content-manager/${(model || this.getCurrentModelName()).toLowerCase()}${(search || this.generateSearch())}`;
|
||||
};
|
||||
|
||||
export {
|
||||
generateFiltersFromSearch,
|
||||
generateSearchFromFilters,
|
||||
generateSearchFromParams,
|
||||
generateRedirectURI,
|
||||
};
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
"containers.SettingsPage.Block.generalSettings.title" : "Allgemeines",
|
||||
"containers.SettingsPage.Block.contentType.title": "Inhaltstypen",
|
||||
"containers.SettingsPage.Block.contentType.description": "Konfiguriere die spezifischen Einstellungen",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "Konfigurieren Sie die Standardeinstellungen für alle Ihre Inhaltstypen.",
|
||||
|
||||
"components.AddFilterCTA.add": "Filter",
|
||||
"components.AddFilterCTA.hide": "Filter",
|
||||
@ -52,6 +53,7 @@
|
||||
"components.TableEmpty.withSearch": "Es gibt keinen {contentType}, der der Suche entspricht ({search})...",
|
||||
|
||||
"form.Input.label": "Label",
|
||||
"form.Input.label.inputDescription": "Dieser Wert überschreibt das im Kopf der Tabelle angezeigte Label.",
|
||||
"form.Input.search": "Suche aktivieren",
|
||||
"form.Input.search.field": "Suche in diesem Feld aktivieren",
|
||||
"form.Input.filters": "Filter aktivieren",
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
"containers.Edit.delete": "Delete",
|
||||
"containers.Edit.reset": "Reset",
|
||||
"containers.Edit.returnList": "Return to list",
|
||||
"containers.Edit.addAnItem": "Add an item...",
|
||||
"containers.Edit.clickToJump": "Click to jump to the entry",
|
||||
"containers.Edit.seeDetails": "Details",
|
||||
"containers.List.addAnEntry": "Add New {entity}",
|
||||
"containers.List.pluginHeaderDescription": "{label} entries found",
|
||||
"containers.List.pluginHeaderDescription.singular": "{label} entry found",
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
"containers.Edit.delete": "Supprimer",
|
||||
"containers.Edit.reset": "Annuler",
|
||||
"containers.Edit.returnList": "Retourner à la liste",
|
||||
"containers.Edit.addAnItem": "Ajouter un élément...",
|
||||
"containers.Edit.clickToJump": "Cliquer pour voir l'entrée",
|
||||
"containers.Edit.seeDetails": "Détails",
|
||||
"containers.List.addAnEntry": "Ajouter {entity}",
|
||||
"containers.List.pluginHeaderDescription": "{label} entrées trouvées",
|
||||
"containers.List.pluginHeaderDescription.singular": "{label} entrée trouvée",
|
||||
|
||||
@ -15,15 +15,31 @@
|
||||
"components.LimitSelect.itemsPerPage": "항목 수 / 페이지",
|
||||
"containers.List.errorFetchRecords": "에러",
|
||||
|
||||
"containers.SettingPage.addField": "새 필드 추가",
|
||||
"containers.SettingPage.attributes": "속성",
|
||||
"containers.SettingPage.attributes.description": "속성의 순서를 지정합니다",
|
||||
|
||||
"containers.SettingPage.listSettings.title": "목록 — 설정",
|
||||
"containers.SettingPage.listSettings.description": "이 콘텐츠 유형의 옵션을 구성합니다.",
|
||||
"containers.SettingPage.pluginHeaderDescription": "이 콘텐츠 유형에 특정한 설정을 구성합니다.",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "모든 콘텐츠 유형에 대한 기본 설정을 구성합니다.",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "콘텐츠 유형에 대한 기본 옵션을 구성합니다.",
|
||||
"containers.SettingsPage.Block.generalSettings.title": "일반",
|
||||
"containers.SettingsPage.Block.contentType.title": "콘텐츠 유형",
|
||||
"containers.SettingsPage.Block.contentType.description": "특정 설정을 구성합니다.",
|
||||
|
||||
"components.AddFilterCTA.add": "필터",
|
||||
"components.AddFilterCTA.hide": "필터",
|
||||
"components.FilterOptions.button.apply": "적용",
|
||||
|
||||
"components.DraggableAttr.edit": "클릭하여 수정",
|
||||
|
||||
"components.FiltersPickWrapper.PluginHeader.actions.apply": "적용",
|
||||
"components.FiltersPickWrapper.PluginHeader.actions.clearAll": "모두 재설정",
|
||||
"components.FiltersPickWrapper.PluginHeader.description": "필터링 조건을 설정하세요.",
|
||||
"components.FiltersPickWrapper.PluginHeader.title.filter": "필터",
|
||||
"components.FiltersPickWrapper.hide": "숨김",
|
||||
|
||||
|
||||
"components.FilterOptions.button.apply": "적용",
|
||||
"components.FilterOptions.FILTER_TYPES.=": "같음",
|
||||
"components.FilterOptions.FILTER_TYPES._ne": "같지 않음",
|
||||
"components.FilterOptions.FILTER_TYPES._lt": "작음",
|
||||
@ -44,11 +60,11 @@
|
||||
"components.TableEmpty.withoutFilter": "{contentType} 목록이 없습니다.",
|
||||
"components.TableEmpty.withSearch": "\"{search}\" 검색. {contentType} 목록이 없습니다.",
|
||||
|
||||
"EditRelations.title": "Relational 데이터",
|
||||
"EditRelations.title": "관계 데이터",
|
||||
|
||||
"emptyAttributes.title": "아직 필드가 없습니다.",
|
||||
"emptyAttributes.description": "첫번째 필드를 추가하세요.",
|
||||
"emptyAttributes.button": "콘텐츠 타입 빌더",
|
||||
"emptyAttributes.button": "콘텐츠 유형 빌더",
|
||||
|
||||
"error.schema.generation": "스키마를 생성하는 도중 에러가 발생했습니다.",
|
||||
"error.records.count": "데이터 수를 가져오는 도중 에러가 발생했습니다.",
|
||||
@ -64,14 +80,26 @@
|
||||
"error.validation.min": "입력한 내용이 너무 작습니다.",
|
||||
"error.validation.maxLength": "입력한 내용이 너무 깁니다.",
|
||||
"error.validation.minLength": "입력한 내용이 너무 짧습니다.",
|
||||
"error.contentTypeName.taken": "이미 사용중인 이름입니다..",
|
||||
"error.attribute.taken": "이미 사용중인 이름입니다..",
|
||||
"error.contentTypeName.taken": "이미 사용중인 이름입니다.",
|
||||
"error.attribute.taken": "이미 사용중인 이름입니다.",
|
||||
"error.attribute.key.taken": "이미 사용중인 키입니다.",
|
||||
"error.attribute.sameKeyAndName": "같은 값을 사용할 수 없습니다.",
|
||||
"error.validation.minSupMax": "이 보다 더 클 수 없습니다.",
|
||||
"error.validation.json": "JSON 형식이 아닙니다.",
|
||||
|
||||
"form.Input.label.inputDescription": "이 값은 테이블 머리에 표시된 라벨을 덮어씌웁니다.",
|
||||
"form.Input.label": "라벨",
|
||||
"form.Input.search": "검색 활성화",
|
||||
"form.Input.search.field": "이 필드에 검색 활성화",
|
||||
"form.Input.filters": "필더 활성화",
|
||||
"form.Input.sort.field": "이 필드에 정렬 활성화",
|
||||
"form.Input.bulkActions": "대규모 액션 활성화",
|
||||
"form.Input.pageEntries": "페이지 당 요소",
|
||||
"form.Input.pageEntries.inputDescription": "참고 : 콘텐츠 유형 설정에서 이 값을 덮어씌울 수 있습니다.",
|
||||
"form.Input.defaultSort": "기본 정렬 속성",
|
||||
|
||||
"notification.error.relationship.fetch": "데이터 관계를 가져오는 도중 에러가 발생했습니다.",
|
||||
"notification.info.SettingPage.disableSort": "정렬이 활성화된 한 개의 속성이 필요합니다.",
|
||||
|
||||
"success.record.delete": "삭제",
|
||||
"success.record.save": "저장",
|
||||
@ -81,6 +109,8 @@
|
||||
"popUpWarning.button.cancel": "취소",
|
||||
"popUpWarning.button.confirm": "확인",
|
||||
"popUpWarning.title": "확인",
|
||||
"popUpWarning.bodyMessage.contentType.delete": "삭제 하시겠습니까?",
|
||||
"popUpWarning.bodyMessage.contentType.delete.all": "모두 삭제 하시겠습니까?"
|
||||
"popUpWarning.bodyMessage.contentType.delete": "삭제하시겠습니까?",
|
||||
"popUpWarning.bodyMessage.contentType.delete.all": "모두 삭제하시겠습니까?",
|
||||
"popUpWarning.warning.cancelAllSettings": "수정 사항을 취소하시겠습니까?",
|
||||
"popUpWarning.warning.updateAllSettings": "모든 설정에 적용됩니다."
|
||||
}
|
||||
|
||||
@ -15,8 +15,24 @@
|
||||
"components.LimitSelect.itemsPerPage": "Registros por página",
|
||||
"containers.List.errorFetchRecords": "Erro",
|
||||
|
||||
"containers.SettingPage.addField": "Adicionar campo",
|
||||
"containers.SettingPage.attributes": "Atributos",
|
||||
"containers.SettingPage.attributes.description": "Define a ordem dos atributos",
|
||||
|
||||
"containers.SettingPage.listSettings.title": "Lista — Configurações",
|
||||
"containers.SettingPage.listSettings.description": "Configure as opções para este Tipo de Conteúdo",
|
||||
"containers.SettingPage.pluginHeaderDescription": "Defina as configurações específicas para este Tipo de Conteúdo",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "Configure as opções padrões para todos os seus Tipos de Conteúdo",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "Configure as opções padrões para seu Tipo de Conteúdo",
|
||||
"containers.SettingsPage.Block.generalSettings.title": "Geral",
|
||||
"containers.SettingsPage.Block.contentType.title": "Tipos de Conteúdo",
|
||||
"containers.SettingsPage.Block.contentType.description": "Defina as configurações específicas",
|
||||
|
||||
"components.AddFilterCTA.add": "Filtros",
|
||||
"components.AddFilterCTA.hide": "Filtros",
|
||||
|
||||
"components.DraggableAttr.edit": "Clique para editar",
|
||||
|
||||
"components.FilterOptions.button.apply": "Aplicar",
|
||||
"components.FiltersPickWrapper.PluginHeader.actions.apply": "Aplicar",
|
||||
"components.FiltersPickWrapper.PluginHeader.actions.clearAll": "Limpar tudo",
|
||||
@ -71,7 +87,19 @@
|
||||
"error.validation.minSupMax": "Não pode ser superior",
|
||||
"error.validation.json": "Isto não corresponde com o formato JSON",
|
||||
|
||||
"form.Input.label.inputDescription": "Este valor substitui o rótulo apresentado no cabeçalho da tabela",
|
||||
"form.Input.label": "Rótulo",
|
||||
"form.Input.search": "Habilitar busca",
|
||||
"form.Input.search.field": "Habilitar busca neste campo",
|
||||
"form.Input.filters": "Habilitar filtros",
|
||||
"form.Input.sort.field": "Habilitar ordenação neste campo",
|
||||
"form.Input.bulkActions": "Habilitar ações em lote",
|
||||
"form.Input.pageEntries": "Entradas por página",
|
||||
"form.Input.pageEntries.inputDescription": "Nota: Você pode substituir este valor na página de configurações do Tipo de Conteúdo.",
|
||||
"form.Input.defaultSort": "Atributo de ordenação padrão",
|
||||
|
||||
"notification.error.relationship.fetch": "Ocorreu um erro durante a busca da relação.",
|
||||
"notification.info.SettingPage.disableSort": "Você precisa de um atributo com permissão de ordenação",
|
||||
|
||||
"success.record.delete": "Removido",
|
||||
"success.record.save": "Salvo",
|
||||
@ -82,5 +110,7 @@
|
||||
"popUpWarning.button.confirm": "Confirmar",
|
||||
"popUpWarning.title": "Por favor, confirme",
|
||||
"popUpWarning.bodyMessage.contentType.delete": "Tem a certeza de que deseja remover este registro?",
|
||||
"popUpWarning.bodyMessage.contentType.delete.all": "Tem a certeza de que deseja remover estes registros?"
|
||||
"popUpWarning.bodyMessage.contentType.delete.all": "Tem a certeza de que deseja remover estes registros?",
|
||||
"popUpWarning.warning.cancelAllSettings": "Você tem certeza de que deseja cancelar suas modificações?",
|
||||
"popUpWarning.warning.updateAllSettings": "Isto irá modificar todas as suas configurações"
|
||||
}
|
||||
@ -1 +1 @@
|
||||
{}
|
||||
{}
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"react-dnd": "^5.0.0",
|
||||
"react-dnd-html5-backend": "^5.0.1",
|
||||
"react-select": "^1.2.1",
|
||||
"react-sortable-hoc": "^0.8.3",
|
||||
"showdown": "^1.8.6",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.13.0.1"
|
||||
},
|
||||
|
||||
@ -49,4 +49,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const exec = require('child_process').execSync;
|
||||
const exec = require('child_process').spawnSync;
|
||||
|
||||
module.exports = {
|
||||
menu: {
|
||||
@ -901,12 +901,12 @@ module.exports = {
|
||||
|
||||
if (connector && !installedConnector) {
|
||||
strapi.log.info(`Installing ${connector} dependency ...`);
|
||||
exec(`npm install ${connector}@alpha`);
|
||||
exec('npm', ['install', `${connector}@alpha`]);
|
||||
}
|
||||
|
||||
if (client && !installedClient) {
|
||||
strapi.log.info(`Installing ${client} dependency ...`);
|
||||
exec(`npm install ${client}`);
|
||||
exec('npm', ['install', client]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
||||
inputDescription={{ id: 'users-permissions.EditForm.inputSelect.description.role' }}
|
||||
inputClassName={styles.inputStyle}
|
||||
label={{ id: 'users-permissions.EditForm.inputSelect.label.role' }}
|
||||
name="settings.default_role"
|
||||
name="advanced.settings.default_role"
|
||||
onChange={this.props.onChange}
|
||||
selectOptions={this.generateSelectOptions()}
|
||||
type="select"
|
||||
@ -54,7 +54,7 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
||||
<Input
|
||||
label={{ id: 'users-permissions.EditForm.inputToggle.label.email' }}
|
||||
inputDescription={{ id: 'users-permissions.EditForm.inputToggle.description.email' }}
|
||||
name="settings.unique_email"
|
||||
name="advanced.settings.unique_email"
|
||||
onChange={this.props.onChange}
|
||||
type="toggle"
|
||||
value={get(this.props.values.settings, 'unique_email')}
|
||||
@ -91,7 +91,7 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
||||
<Input
|
||||
label={{ id: 'users-permissions.EditForm.inputToggle.label.sign-up' }}
|
||||
inputDescription={{ id: 'users-permissions.EditForm.inputToggle.description.sign-up' }}
|
||||
name="settings.allow_register"
|
||||
name="advanced.settings.allow_register"
|
||||
onChange={this.props.onChange}
|
||||
type="toggle"
|
||||
value={get(this.props.values.settings, 'allow_register')}
|
||||
|
||||
@ -43,6 +43,8 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
|
||||
|
||||
getRedirectURIProviderConf = () => { // NOTE: Still testings providers so the switch statement is likely to change
|
||||
switch (this.props.dataToEdit) {
|
||||
case 'discord':
|
||||
return `${strapi.backendURL}/connect/discord/callback`;
|
||||
case 'facebook':
|
||||
return `${strapi.backendURL}/connect/facebook/callback`;
|
||||
case 'google':
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { findIndex } from 'lodash';
|
||||
import { findIndex, get } from 'lodash';
|
||||
import { takeLatest, put, fork, take, cancel, select, call } from 'redux-saga/effects';
|
||||
|
||||
import request from 'utils/request';
|
||||
@ -64,7 +64,7 @@ export function* dataFetch(action) {
|
||||
export function* submitData(action) {
|
||||
try {
|
||||
const body = yield select(makeSelectModifiedData());
|
||||
const opts = { method: 'PUT', body: (action.endPoint === 'advanced') ? body.settings : body };
|
||||
const opts = { method: 'PUT', body: (action.endPoint === 'advanced') ? get(body, ['advanced', 'settings'], {}) : body };
|
||||
|
||||
yield call(request, `/users-permissions/${action.endPoint}`, opts);
|
||||
yield put(submitSucceeded());
|
||||
|
||||
@ -163,6 +163,7 @@
|
||||
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.redirectURL.front-end.label": "The redirect URL to your front-end app",
|
||||
|
||||
"PopUpForm.Providers.discord.providerConfig.redirectURL": "The redirect URL to add in your Discord application configurations",
|
||||
"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",
|
||||
|
||||
@ -1 +1,144 @@
|
||||
{}
|
||||
{
|
||||
"Auth.form.button.register-success" : "Invia di nuovo",
|
||||
"Auth.form.button.forgot-password.success" : "Invia di nuovo",
|
||||
"Auth.form.button.forgot-password" : "Invia Email",
|
||||
"Auth.form.button.reset-password" : "Cambia password",
|
||||
"Auth.form.button.login" : "Accedi",
|
||||
"Auth.form.button.register" : "Inizia adesso",
|
||||
"Auth.form.error.noAdminAccess" : "Non puoi accedere al pannello di amministrazione.",
|
||||
"Auth.form.forgot-password.email.label" : "Inserisci la tua email",
|
||||
"Auth.form.forgot-password.email.label.success" : "Email inviata correttamente",
|
||||
"Auth.form.forgot-password.email.placeholder" : "mysuperemail@gmail.com",
|
||||
"Auth.header.register.description" : "Per terminare l'installazione e mettere in sicurezza la tua applicazione è necessario creare il primo utente (root admin) inserendo le informazioni necessarie di seguito riportate",
|
||||
"Auth.form.header.login" : "strapi",
|
||||
"Auth.form.header.forgot-password" : "strapi",
|
||||
"Auth.form.header.register" : "Benvenuto!",
|
||||
"Auth.form.header.register-success" : "strapi",
|
||||
"Auth.form.login.password.label" : "Password",
|
||||
"Auth.form.login.rememberMe.label" : "Ricordati di me",
|
||||
"Auth.form.login.username.label" : "Username",
|
||||
"Auth.form.login.username.placeholder" : "John Doe",
|
||||
"Auth.form.register.email.label" : "Email",
|
||||
"Auth.form.register.email.placeholder" : "johndoe@gmail.com",
|
||||
"Auth.form.register.username.label" : "Username",
|
||||
"Auth.form.register.username.placeholder" : "John Doe",
|
||||
"Auth.form.register.password.label" : "Password",
|
||||
"Auth.form.register.confirmPassword.label" : "Password di conferma",
|
||||
"Auth.form.register.news.label" : "Tienimi aggiornato su nuove funzionalità e futuri miglioramenti",
|
||||
"Auth.form.register-success.email.label" : "Email inviata con successo a",
|
||||
"Auth.form.register-success.email.placeholder" : "mysuperemail@gmail.com",
|
||||
"Auth.form.error.email.provide" : "Per favore fornisci il tuo username o la tua password",
|
||||
"Auth.form.error.email.invalid" : "Questa email non è valida.",
|
||||
"Auth.form.error.password.provide" : "Per favore fornisci la tua password",
|
||||
"Auth.form.error.invalid" : "Identificatore o password non valida.",
|
||||
"Auth.form.error.password.local" : "Questo utente non ha mai impostato una password locale, accedi gentilmente tramite il provider usato durante la creazione dell'account",
|
||||
"Auth.form.error.password.format" : "La tua password non può contenere il simbolo $ per più di tre volte.",
|
||||
"Auth.form.error.user.not-exist" : "Questa email non esiste.",
|
||||
"Auth.form.error.code.provide" : "Codice fornito non corretto.",
|
||||
"Auth.form.error.password.matching" : "La password non corrisponde.",
|
||||
"Auth.form.error.params.provide" : "I parametri forniti non sono corretti.",
|
||||
"Auth.form.error.username.taken" : "Username in uso",
|
||||
"Auth.form.error.email.taken" : "Email in uso",
|
||||
"Auth.link.forgot-password" : "Password dimenticata?",
|
||||
"Auth.link.ready" : "Sei pronto per accedere?",
|
||||
"BoundRoute.title" : "Percorso vincolato a",
|
||||
"components.Input.error.password.noMatch" : "La password non corrisponde",
|
||||
"Controller.input.label" : "{label}",
|
||||
"Controller.selectAll" : "Seleziona tutto",
|
||||
"EditForm.inputSelect.label.role" : "Ruolo di default per gli utenti autenticati",
|
||||
"EditForm.inputSelect.description.role" : "Questa operazione associerà i nuovi utenti autenticati al ruolo selezionato.",
|
||||
"EditForm.inputSelect.subscriptions.label" : "Gestisci le sottoscrizioni di quota",
|
||||
"EditForm.inputSelect.subscriptions.description" : "Limita il numero di sottoscrizioni per IP per ora.",
|
||||
"EditForm.inputSelect.durations.label" : "Durata",
|
||||
"EditForm.inputSelect.durations.description" : "Numero di ore in cui l'utente non può registrarsi",
|
||||
"EditForm.inputToggle.label.email" : "Un account per indirizzo email",
|
||||
"EditForm.inputToggle.label.sign-up" : "Abilita iscrizioni",
|
||||
"EditForm.inputToggle.description.email" : "Non consentire all'utente di creare account multipli usando lo stesso indirizzo email con fornitori di autenticazione diversi.",
|
||||
"EditForm.inputToggle.description.sign-up" : "Quando disabilitata (OFF), il processo di registrazione è proibito. Nessuno può iscriversi indipendentemente dal fornitore utilizzato.",
|
||||
"EditPage.cancel" : "Cancella",
|
||||
"EditPage.submit" : "Salva",
|
||||
"EditPage.form.roles" : "Dettagli del ruolo",
|
||||
"EditPage.form.roles.label.description" : "Descrizione",
|
||||
"EditPage.form.roles.label.name" : "Nome",
|
||||
"EditPage.form.roles.label.users" : "Utente associato con questo ruolo ({number})",
|
||||
"EditPage.form.roles.name.error" : "Questo valore è obbligatorio",
|
||||
"EditPage.header.title" : "{name}",
|
||||
"EditPage.header.title.create" : "Crea un nuovo ruolo",
|
||||
"EditPage.header.description" : "{description}",
|
||||
"EditPage.header.description.create" : "Crea",
|
||||
"EditPage.notification.permissions.error" : "Si è verificato un errore durante il recupero dei permessi",
|
||||
"EditPage.notification.policies.error" : "Si è verificato un errore durante il recupero delle policy",
|
||||
"EditPage.notification.role.error" : "Si è verificato un errore durante il recupero del ruolo",
|
||||
"eaderNav.link.advancedSettings" : "Impostazioni avanzate",
|
||||
"HeaderNav.link.emailTemplates" : "Template delle Email",
|
||||
"HeaderNav.link.providers" : "Providers",
|
||||
"HeaderNav.link.roles" : "Ruoli e permessi",
|
||||
"HomePage.header.title" : "Ruoli e permessi",
|
||||
"HomePage.header.description" : "Definisci i ruoli e i permessi per i tuoi utenti.",
|
||||
"InputSearch.placeholder" : "Cerca un utente",
|
||||
"List.button.roles" : "Aggiungi un ruolo",
|
||||
"List.button.providers" : "Aggiungi un nuovo Provider",
|
||||
"List.title.emailTemplates.singular" : "{number} template per le email disponibile",
|
||||
"List.title.emailTemplates.plural" : "{number} template per le email disponibili",
|
||||
"List.title.providers.disabled.singular" : "{number} disabilitato",
|
||||
"List.title.providers.disabled.plural" : "{number} sono disabilitati",
|
||||
"List.title.providers.enabled.singular" : "{number} provider è abilitato e",
|
||||
"List.title.providers.enabled.plural" : "{number} providers sono disponibili e",
|
||||
"List.title.roles.singular" : "{number} ruolo disponibile",
|
||||
"List.title.roles.plural" : "{number} ruoli disponibili",
|
||||
"notification.error.delete" : "Si è verificato un errore mentre si stava cercando di eliminare l'elemento",
|
||||
"notification.error.fetch" : "Si è verificato un errore mentre si stava cercando di recuperare i dati",
|
||||
"notification.error.fetchUser" : "Si è verificato un errore mentre si stava cercando di recuperare gli utenti",
|
||||
"notification.info.emailSent" : "Email inviata",
|
||||
"notification.success.delete" : "L'elemento è stato eliminato",
|
||||
"notification.success.submit" : "Impostazioni aggiornate",
|
||||
"plugin.description.short" : "Proteggi le tue API con un processo completo di autenticazione basato su JWT",
|
||||
"plugin.description.long" : "Proteggi le tue API con un processo completo di autenticazione basato su JWT. Questo plugin è implementato con una strategia ACL che ti consente di gestire i permessi tra i gruppi di utenti.",
|
||||
"Plugin.permissions.application.description" : "Definire tutte le azioni consentite per il tuo progetto.",
|
||||
"Plugin.permissions.plugins.description" : "Definire tutte le azioni consentite per il plugin {name}.",
|
||||
"Plugins.header.title" : "Permessi",
|
||||
"Plugins.header.description" : "Solo le azioni guidate da un percorso sono elencate sotto.",
|
||||
"Policies.InputSelect.empty" : "Nessuno",
|
||||
"Policies.InputSelect.label" : "Consenti di eseguire questa azione per:",
|
||||
"Policies.header.hint" : "Seleziona le azioni dell'applicazione o del plugin e clicca sull'icona cog per mostrare il percorso corrispondente",
|
||||
"Policies.header.title" : "Impostazioni avanzate",
|
||||
"Email.template.validation_email" : "Validazione dell'indirizzo Email",
|
||||
"Email.template.reset_password" : "Reset password",
|
||||
"Email.template.success_register" : "Registrazione avvenuta",
|
||||
"Auth.advanced.allow_register" : "Registrazione consentita",
|
||||
"PopUpForm.button.cancel" : "Cancella",
|
||||
"PopUpForm.button.save" : "Salva",
|
||||
"PopUpForm.header.add.providers" : "Aggiungi nuovo Provider",
|
||||
"PopUpForm.header.edit.email-templates" : "Modifica il template delle Email",
|
||||
"PopUpForm.header.edit.providers" : "Modifica {provider} Provider",
|
||||
"PopUpForm.inputSelect.providers.label" : "Scegli il provider",
|
||||
"PopUpForm.Email.options.from.name.label" : "Nome del mittente",
|
||||
"PopUpForm.Email.options.from.email.label" : "Email del mittente",
|
||||
"PopUpForm.Email.options.response_email.label" : "Email di risposta",
|
||||
"PopUpForm.Email.options.object.label" : "Soggetto",
|
||||
"PopUpForm.Email.options.message.label" : "Messaggio",
|
||||
"PopUpForm.Email.validation_email.options.object.placeholder" : "Conferma gentilmente il tuo indirizzo email per %APP_NAME%",
|
||||
"PopUpForm.Email.reset_password.options.object.placeholder" : "Conferma gentilmente il tuo indirizzo email per %APP_NAME%",
|
||||
"PopUpForm.Email.success_register.options.object.placeholder" : "Conferma gentilmente il tuo indirizzo email per %APP_NAME%",
|
||||
"PopUpForm.Email.validation_email.options.message.placeholder" : "Clicca su questo link per validare il tuo account",
|
||||
"PopUpForm.Email.reset_password.options.message.placeholder" : "Clicca su questo link per validare il tuo account",
|
||||
"PopUpForm.Email.success_register.options.message.placeholder" : "Clicca su questo link per validare il tuo account",
|
||||
"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" : "Abilita",
|
||||
"PopUpForm.Providers.enabled.description" : "Se disabilitato, gli utenti non potranno usare questo provider.",
|
||||
"opUpForm.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 di redirect per la tua app di front-end",
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL" : "L'URL di redirect per aggiungere la tua configurazione dell'applicazione Facebook",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL" : "L'URL di redirect per aggiungere la tua configurazione dell'applicazione Google",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL" : "L'URL di redirect per aggiungere la tua configurazione dell'applicazione Github",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL" : "L'URL di redirect per aggiungere la tua configurazione dell'applicazione Linkdin",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL" : "L'URL di redirect per aggiungere la tua configurazione dell'applicazione Twitter",
|
||||
"PopUpForm.Providers.callback.placeholder" : "TEXT",
|
||||
"PopUpForm.Email.email_templates.inputDescription" : "Se non sai bene come usare le variabili, {link}",
|
||||
"PopUpForm.Email.link.documentation" : "controlla la documentazione"
|
||||
}
|
||||
|
||||
@ -39,6 +39,17 @@ module.exports = async cb => {
|
||||
enabled: true,
|
||||
icon: 'envelope'
|
||||
},
|
||||
discord: {
|
||||
enabled: false,
|
||||
icon: 'comments',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/discord/callback',
|
||||
scope: [
|
||||
'identify',
|
||||
'email'
|
||||
]
|
||||
},
|
||||
facebook: {
|
||||
enabled: false,
|
||||
icon: 'facebook-official',
|
||||
|
||||
@ -14,6 +14,12 @@ module.exports = strapi => {
|
||||
},
|
||||
|
||||
initialize: function(cb) {
|
||||
_.forEach(strapi.admin.config.routes, value => {
|
||||
if (_.get(value.config, 'policies')) {
|
||||
value.config.policies.unshift('plugins.users-permissions.permissions');
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(strapi.config.routes, value => {
|
||||
if (_.get(value.config, 'policies')) {
|
||||
value.config.policies.unshift('plugins.users-permissions.permissions');
|
||||
|
||||
@ -40,4 +40,4 @@
|
||||
"configurable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +109,40 @@ const getProfile = async (provider, query, callback) => {
|
||||
}).get();
|
||||
|
||||
switch (provider) {
|
||||
case 'discord': {
|
||||
const discord = new Purest({
|
||||
provider: 'discord',
|
||||
config: {
|
||||
'discord': {
|
||||
'https://discordapp.com/api/': {
|
||||
'__domain': {
|
||||
'auth': {
|
||||
'auth': {'bearer': '[0]'}
|
||||
}
|
||||
},
|
||||
'{endpoint}': {
|
||||
'__path': {
|
||||
'alias': '__default'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
discord.query().get('users/@me').auth(access_token).request((err, res, body) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
// Combine username and discriminator because discord username is not unique
|
||||
var username = body.username + '#' + body.discriminator;
|
||||
callback(null, {
|
||||
username: username,
|
||||
email: body.email
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'facebook': {
|
||||
const facebook = new Purest({
|
||||
provider: 'facebook'
|
||||
|
||||
@ -116,7 +116,9 @@ module.exports = {
|
||||
}, {}));
|
||||
|
||||
const appControllers = Object.keys(strapi.api || {}).reduce((acc, key) => {
|
||||
acc.controllers[key] = generateActions(strapi.api[key].controllers[key]);
|
||||
Object.keys(strapi.api[key].controllers).forEach((controller) => {
|
||||
acc.controllers[controller] = generateActions(strapi.api[key].controllers[controller]);
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, { controllers: {} });
|
||||
@ -203,7 +205,7 @@ module.exports = {
|
||||
const databasePermissions = await strapi.query('permission', 'users-permissions').find();
|
||||
const actions = databasePermissions
|
||||
.map(permission => `${permission.type}.${permission.controller}.${permission.action}`);
|
||||
|
||||
|
||||
|
||||
// Aggregate first level actions.
|
||||
const appActions = Object.keys(strapi.api || {}).reduce((acc, api) => {
|
||||
|
||||
@ -43,4 +43,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -43,4 +43,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -39,4 +39,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -13,4 +13,4 @@
|
||||
"pkgcloud": "^1.5.0",
|
||||
"streamifier": "^0.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,4 +49,4 @@
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ module.exports = function (plugin, cliArguments) {
|
||||
|
||||
if (!isStrapiInstalledWithNPM) {
|
||||
// Create the directory yarn doesn't do it it
|
||||
shell.exec(`mkdir ${pluginPath}`);
|
||||
shell.exec('mkdir', [pluginPath]);
|
||||
// Add a package.json so it installs the dependencies
|
||||
shell.touch(`${pluginPath}/package.json`);
|
||||
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify({}), 'utf8');
|
||||
|
||||
@ -66,7 +66,8 @@ module.exports = function(appPath = '') {
|
||||
};
|
||||
|
||||
const setFilesToWatch = (src) => {
|
||||
var files = fs.readdirSync(src);
|
||||
let files = _.includes(src, '/admin') || _.includes(src, 'components') ? [] : fs.readdirSync(src);
|
||||
|
||||
_.forEach(files, file => {
|
||||
if (
|
||||
_.startsWith(file, '.') ||
|
||||
|
||||
@ -91,4 +91,4 @@
|
||||
},
|
||||
"preferGlobal": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user