mirror of
https://github.com/strapi/strapi.git
synced 2025-07-24 01:18:17 +00:00
Merge branch 'master' into discordProvider
This commit is contained in:
commit
f559bcc82c
@ -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: 19px 0 20px;
|
||||
}
|
||||
|
@ -6,15 +6,46 @@
|
||||
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
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';
|
||||
|
||||
// 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';
|
||||
|
||||
const SortableItem = SortableElement(({idx, onRemove, item, onClick}) => {
|
||||
return (
|
||||
<li className={styles.sortableListItem}>
|
||||
<div>
|
||||
<div className={styles.dragHandle}><span></span></div>
|
||||
<span className="sortable-item--value" onClick={() => onClick(item)}>{item.label}</span>
|
||||
</div>
|
||||
<div className={styles.sortableListItemActions}>
|
||||
<img src={IconRemove} alt="Remove Icon" onClick={() => onRemove(idx)} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
const SortableList = SortableContainer(({items, onRemove, onClick}) => {
|
||||
return (
|
||||
<ul className={styles.sortableList}>
|
||||
{items.map((item, index) => (
|
||||
<SortableItem key={`item-${index}`} index={index} idx={index} item={item} onRemove={onRemove} onClick={onClick} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
});
|
||||
|
||||
class SelectMany extends React.Component {
|
||||
// eslint-disable-line react/prefer-stateless-function
|
||||
constructor(props) {
|
||||
@ -92,13 +123,12 @@ 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],
|
||||
};
|
||||
|
||||
this.props.setRecordAttribute({ target });
|
||||
@ -121,6 +151,35 @@ 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),
|
||||
};
|
||||
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,7 +187,7 @@ 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}`}>
|
||||
@ -140,10 +199,9 @@ class SelectMany extends React.Component {
|
||||
id={this.props.relation.alias}
|
||||
isLoading={this.state.isLoading}
|
||||
onMenuScrollToBottom={this.handleBottomScroll}
|
||||
onInputChange={this.handleInputChange}
|
||||
onSelectResetsInput={false}
|
||||
multi
|
||||
value={
|
||||
/>
|
||||
<SortableList
|
||||
items={
|
||||
isNull(value) || isUndefined(value) || value.size === 0
|
||||
? null
|
||||
: value.map(item => {
|
||||
@ -159,6 +217,10 @@ class SelectMany extends React.Component {
|
||||
}
|
||||
})
|
||||
}
|
||||
onSortEnd={this.handleSortEnd}
|
||||
onRemove={this.handleRemove}
|
||||
distance={1}
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -167,6 +229,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,
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
label + div{
|
||||
margin: 5px 0 26px;
|
||||
margin: 3px 0 26px;
|
||||
|
||||
&:focus{
|
||||
outline: none;
|
||||
@ -25,3 +25,116 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sortableList {
|
||||
margin-top: -21px;
|
||||
padding-left: 0 !important;
|
||||
list-style: none !important;
|
||||
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,15 @@ export class EditPage extends React.Component {
|
||||
this.props.changeData({ target });
|
||||
}
|
||||
|
||||
handleRedirect = ({ model, id, source = 'content-manager'}) => {
|
||||
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}` })}`,
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const formErrors = checkFormValidity(this.generateFormFromRecord(), this.props.editPage.formValidations);
|
||||
@ -330,6 +352,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,
|
||||
};
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -14,6 +14,14 @@ module.exports = strapi => {
|
||||
},
|
||||
|
||||
initialize: function(cb) {
|
||||
console.log();
|
||||
_.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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user