diff --git a/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_grab.svg b/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_grab.svg
new file mode 100644
index 0000000000..da187b6f13
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_grab.svg
@@ -0,0 +1,34 @@
+
+
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_remove.svg b/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_remove.svg
new file mode 100644
index 0000000000..594f147935
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/assets/images/icon_remove.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/index.js b/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/index.js
index 96bf90c636..14b002eac0 100644
--- a/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/index.js
@@ -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 (
-
- {(message) => {message}
}
-
{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,
};
diff --git a/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/styles.scss b/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/styles.scss
index 7c0056c788..efa65641f8 100644
--- a/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/styles.scss
+++ b/packages/strapi-plugin-content-manager/admin/src/components/EditRelations/styles.scss
@@ -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;
}
diff --git a/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/index.js b/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/index.js
index 22d95a29fd..13c7572c5f 100644
--- a/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/index.js
@@ -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 (
+
+
+
+
onClick(item)}>{item.label}
+
+
+

onRemove(idx)} />
+
+
+ );
+});
+
+const SortableList = SortableContainer(({items, onRemove, onClick}) => {
+ return (
+
+ {items.map((item, index) => (
+
+ ))}
+
+ );
+});
+
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 ? (
{this.props.relation.description}
@@ -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 (
@@ -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={
+ />
+ {
@@ -159,6 +217,10 @@ class SelectMany extends React.Component {
}
})
}
+ onSortEnd={this.handleSortEnd}
+ onRemove={this.handleRemove}
+ distance={1}
+ onClick={this.handleClick}
/>
);
@@ -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,
diff --git a/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/styles.scss b/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/styles.scss
index c752aabc81..5d87d5133d 100644
--- a/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/styles.scss
+++ b/packages/strapi-plugin-content-manager/admin/src/components/SelectMany/styles.scss
@@ -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;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/actions.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/actions.js
index bb6f62d9ef..e7aeddead1 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/actions.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/actions.js
@@ -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;
}, {});
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
index cffe9faab2..06587a8f8e 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
@@ -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}
/>
)}
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js
index 96cf507608..f20ffd8ff8 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js
@@ -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
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
index 12cfe08b99..5b9915c89c 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
@@ -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 {
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/utils.js b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/utils.js
index 67346e92bb..6ce34da080 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/utils.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/utils.js
@@ -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,
};
diff --git a/packages/strapi-plugin-content-manager/package.json b/packages/strapi-plugin-content-manager/package.json
index 39cdc52f5b..6689bb8c02 100755
--- a/packages/strapi-plugin-content-manager/package.json
+++ b/packages/strapi-plugin-content-manager/package.json
@@ -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"
},
diff --git a/packages/strapi-plugin-users-permissions/admin/src/translations/it.json b/packages/strapi-plugin-users-permissions/admin/src/translations/it.json
index 9e26dfeeb6..9ce4cc3902 100644
--- a/packages/strapi-plugin-users-permissions/admin/src/translations/it.json
+++ b/packages/strapi-plugin-users-permissions/admin/src/translations/it.json
@@ -1 +1,144 @@
-{}
\ No newline at end of file
+{
+ "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"
+}
diff --git a/packages/strapi-plugin-users-permissions/middlewares/users-permissions/index.js b/packages/strapi-plugin-users-permissions/middlewares/users-permissions/index.js
index 7e9d41dd19..03da8be28b 100644
--- a/packages/strapi-plugin-users-permissions/middlewares/users-permissions/index.js
+++ b/packages/strapi-plugin-users-permissions/middlewares/users-permissions/index.js
@@ -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');
diff --git a/packages/strapi-plugin-users-permissions/models/User.settings.json b/packages/strapi-plugin-users-permissions/models/User.settings.json
index da72db76e3..99479b1cba 100644
--- a/packages/strapi-plugin-users-permissions/models/User.settings.json
+++ b/packages/strapi-plugin-users-permissions/models/User.settings.json
@@ -40,4 +40,4 @@
"configurable": false
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/strapi-plugin-users-permissions/services/UsersPermissions.js b/packages/strapi-plugin-users-permissions/services/UsersPermissions.js
index a8190c8ba8..5e25932e77 100644
--- a/packages/strapi-plugin-users-permissions/services/UsersPermissions.js
+++ b/packages/strapi-plugin-users-permissions/services/UsersPermissions.js
@@ -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) => {