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 @@ + + + + Icon grab + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + + + Icon remove + Created with Sketch. + + + + + + + + + + + + + + \ 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} +
    +
    + Remove Icon onRemove(idx)} /> +
    +
  • + ); +}); + +const SortableList = SortableContainer(({items, onRemove, onClick}) => { + return ( + + ); +}); + 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) => {