Merge branch 'master' into feature/allow-filtering-on-a-relation-attribute

This commit is contained in:
Kamal Bennani Bouchiba 2018-11-20 19:34:46 +01:00 committed by GitHub
commit 6482a6ec84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 317 additions and 56 deletions

View File

@ -3,15 +3,17 @@
<!-- Uncomment the correct contribution type. !-->
My PR is a:
<!-- 💥 Breaking change -->
<!-- 🐛 Bug fix -->
<!-- 💅 Enhancement -->
<!-- 🚀 New feature -->
- [ ] 💥 Breaking change
- [ ] 🐛 Bug fix #issueNumber
- [ ] 💅 Enhancement
- [ ] 🚀 New feature
Main update on the:
<!-- Admin -->
<!-- Documentation -->
<!-- Framework -->
<!-- Plugin -->
- [ ] Admin
- [ ] Documentation
- [ ] Framework
- [ ] Plugin
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
<!-- ⚠️ Please link issue(s) you close / fix by using GitHub keywords https://help.github.com/articles/closing-issues-using-keywords/ !-->

View File

@ -74,7 +74,7 @@ To use the providers authentication, set your credentials in
Redirect your user to: `GET /connect/:provider`.
After his approval, he will be redirected to `/auth/:provider/callback`. The jwt and user will be available in the querystring.
After their approval, they will be redirected to `/auth/:provider/callback`. The jwt and user will be available in the querystring.
Response payload:

View File

@ -296,7 +296,7 @@ A `product` can be related to many `categories`, so a `category` can have many `
```
::: note
The `dominant` key allows you to define in which table/collection (only for NoSQL databases) should be stored the array that defines the relationship. Because there is no join table in NoSQL, this key is required for NoSQL databases (ex: MongoDB).
(NoSQL databases only) The `dominant` key defines which table/collection should store the array that defines the relationship. Because there are no join tables in NoSQL, this key is required for NoSQL databases (ex: MongoDB).
:::
**Path —** `./api/category/models/Category.settings.json`.

View File

@ -0,0 +1,95 @@
/*
* Copyright@React-FullStory (https://github.com/cereallarceny/react-fullstory)
*/
import React from 'react';
import PropTypes from 'prop-types';
const canUseDOM = !!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
export const getWindowFullStory = () => window[window['_fs_namespace']];
class FullStory extends React.Component {
constructor(props) {
super(props);
window['_fs_debug'] = false;
window['_fs_host'] = 'fullstory.com';
window['_fs_org'] = props.org;
window['_fs_namespace'] = 'FS';
(function(m,n,e,t,l,o,g,y) {
if (e in m) {
if(m.console && m.console.log) {
m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');
}
return;
}
g = m[e]= function(a,b,s) {
g.q ? g.q.push([a,b,s]) : g._api(a,b,s);
};
g.q=[];
o = n.createElement(t);
o.async = 1;
o.src = `https://${window._fs_host}/s/fs.js`;
y = n.getElementsByTagName(t)[0];
y.parentNode.insertBefore(o,y);
g.identify = function(i,v,s) {
g(l,{ uid:i },s);
if (v) {
g(l,v,s);
}
};
g.setUserVars = function(v,s) {
g(l,v,s);
};
g.event = function(i,v,s) {
g('event',{ n:i,p:v },s);
};
g.shutdown = function() {
g("rec",!1);
};
g.restart = function() {
g("rec",!0);
};
g.consent = function(a) {
g("consent",!arguments.length||a);
};
g.identifyAccount = function(i,v) {
o = 'account';
v = v||{};
v.acctId = i;
g(o,v);
};
g.clearUserCookie = function() {};
})(window, document, window['_fs_namespace'], 'script', 'user');
}
shouldComponentUpdate() {
return false;
}
componentWillUnmount() {
if (!canUseDOM || !getWindowFullStory()) return false;
getWindowFullStory().shutdown();
delete getWindowFullStory();
}
render() {
return false;
}
}
FullStory.propTypes = {
org: PropTypes.string.isRequired,
};
export default FullStory;

View File

@ -1,3 +1,3 @@
{
"languages": ["en", "ar", "es", "fr", "de", "it", "ko", "nl", "pl", "pt", "pt-BR", "ru", "tr", "zh", "zh-Hans", "ja"]
"languages": ["en", "ar", "es", "fa", "fr", "de", "it", "ko", "nl", "pl", "pt", "pt-BR", "ru", "tr", "zh", "zh-Hans", "ja"]
}

View File

@ -43,6 +43,7 @@ import Logout from 'components/Logout';
import NotFoundPage from 'containers/NotFoundPage/Loadable';
import OverlayBlocker from 'components/OverlayBlocker';
import PluginPage from 'containers/PluginPage';
import FullStory from 'components/FullStory';
// Utils
import auth from 'utils/auth';
import injectReducer from 'utils/injectReducer';
@ -73,12 +74,12 @@ export class AdminPage extends React.Component {
}
componentDidUpdate(prevProps) {
const { adminPage: { allowGa }, location: { pathname }, plugins } = this.props;
const { adminPage: { uuid }, location: { pathname }, plugins } = this.props;
if (prevProps.location.pathname !== pathname) {
this.checkLogin(this.props);
if (allowGa) {
if (uuid) {
ReactGA.pageview(pathname);
}
}
@ -198,6 +199,7 @@ export class AdminPage extends React.Component {
return (
<div className={styles.adminPage}>
{this.props.adminPage.uuid ? <FullStory org="GK708" /> : ''}
{this.showLeftMenu() && (
<LeftMenu
plugins={this.retrievePlugins()}

View File

@ -11,7 +11,7 @@ import {
} from './constants';
const initialState = fromJS({
allowGa: true,
uuid: false,
currentEnvironment: 'development',
isLoading: true,
layout: Map({}),
@ -22,7 +22,7 @@ function adminPageReducer(state = initialState, action) {
switch (action.type) {
case GET_ADMIN_DATA_SUCCEEDED:
return state
.update('allowGa', () => action.data.allowGa)
.update('uuid', () => action.data.uuid)
.update('currentEnvironment', () => action.data.currentEnvironment)
.update('layout', () => Map(action.data.layout))
.update('strapiVersion', () => action.data.strapiVersion)

View File

@ -16,13 +16,13 @@ function* getData() {
yield call(request, `${strapi.backendURL}/users/me`, { method: 'GET' });
}
const [{ allowGa }, { strapiVersion }, { currentEnvironment }, { layout }] = yield all([
const [{ uuid }, { strapiVersion }, { currentEnvironment }, { layout }] = yield all([
call(request, '/admin/gaConfig', { method: 'GET' }),
call(request, '/admin/strapiVersion', { method: 'GET' }),
call(request, '/admin/currentEnvironment', { method: 'GET' }),
call(request, '/admin/layout', { method: 'GET' }),
]);
yield put(getAdminDataSucceeded({ allowGa, strapiVersion, currentEnvironment, layout }));
yield put(getAdminDataSucceeded({ uuid, strapiVersion, currentEnvironment, layout }));
} catch(err) {
console.log(err); // eslint-disable-line no-console

View File

@ -37,6 +37,8 @@ export class LocaleToggle extends React.Component { // eslint-disable-line
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/kr.svg';
case 'ja':
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/jp.svg';
case 'fa':
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/ir.svg';
default:
return `https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/${locale}.svg`;
}

View File

@ -0,0 +1,141 @@
{
"Analytics": "آنالیز",
"Content Manager": "مدیریت محتوا",
"Content Type Builder": "سازنده ی الگوی محتوایی",
"Email": "ایمیل",
"Files Upload": "آپلود فایل",
"HomePage.notification.newsLetter.success": "موفقیت در اشتراک خبر نامه",
"New entry": "رکورد جدید",
"Password": "رمز عبور",
"Provider": "سرویس دهنده",
"ResetPasswordToken": "بازنشانی رمز عبور",
"Role": "نقش",
"Roles & Permissions": "نقش ها و دسترسی ها",
"Settings Manager": "مدیریت تنظیمات",
"Username": "نام کاربری",
"Users": "کاربران",
"Users & Permissions": "کاربران و دسترسی ها",
"app.components.BlockLink.code": "نمونه کد",
"app.components.BlockLink.code.content": "با بررسی و آزمایش پروژه های واقعی توسط جامعه توسعه دهنده Strapi را یاد بگیرید.",
"app.components.BlockLink.documentation": "خواندن مستندات",
"app.components.BlockLink.documentation.content": "مفاهیم، راهنمای مرجع و آموزش ها را فرا بگیرید.",
"app.components.Button.cancel": "کنسل",
"app.components.Button.save": "ذخیره",
"app.components.ComingSoonPage.comingSoon": "بزودی",
"app.components.ComingSoonPage.featuresNotAvailable": "این ویژگی هنوز در حال توسعه است.",
"app.components.DownloadInfo.download": "در حال دانلود...",
"app.components.DownloadInfo.text": "ممکن است دقایقی طول بکشد، با تشکر از شکیبایی شما.",
"app.components.EmptyAttributes.title": "هیچ فیلدی وجود ندارد",
"app.components.HomePage.button.blog": "مشاهده بیشتر در بلاگ",
"app.components.HomePage.button.quickStart": "شروع آموزش سریع",
"app.components.HomePage.community": "جستجوی جامعه توسعه دهنده در اینترنت",
"app.components.HomePage.community.content": "گفتگو با اعضای تیم و توسعه دهندگان در کانال های مختلف ارتباطی",
"app.components.HomePage.create": "ساخت اولین الگوی محتوا",
"app.components.HomePage.createBlock.content.first": "این ",
"app.components.HomePage.createBlock.content.second": " افزونه به شما کمک میکند مدل ساختاری داده های خود را تعریف کنید،اگر شما جدیدا به اینجا مراجعه کردید، پس حتما مارا دنبال کنید ",
"app.components.HomePage.createBlock.content.tutorial": " آموزش.",
"app.components.HomePage.cta": "تایید",
"app.components.HomePage.newsLetter": "برای آگاهی از آخرین اخبار Strapi مشترک خبرنامه شوید.",
"app.components.HomePage.support": "مارا حمایت کنید",
"app.components.HomePage.support.content": "با خرید تی شرت ما میتوانیم به توسعه Strapi ادامه داده و بهترین تجربه را برای شما فراهم کنیم!",
"app.components.HomePage.support.link": "هم اکنون تی شرت خود را دریافت کنید",
"app.components.HomePage.welcome": "خوش آمدید!",
"app.components.HomePage.welcome.again": "خوش آمدید ",
"app.components.HomePage.welcomeBlock.content": "خرسندیم که شما را به عنوان عضوی از جامعه توسعه دهنده بشناسیم، ما هر لحظه به دنبال دریافت بازخورد شما هستیم، در ارسال بازخورد تردید نکنید ",
"app.components.HomePage.welcomeBlock.content.again": "امیدواریم در پروژه خود پیشرفت کنید... میتوانید در مورد آخرین های Strapi مطالعه کنید. بر اساس بازخورد شما ما موثر ترین اقدامات را برای بهبود محصول انجام خواهیم داد.",
"app.components.HomePage.welcomeBlock.content.issues": "مشکلات.",
"app.components.HomePage.welcomeBlock.content.raise": " یا ارتقاء دهید ",
"app.components.ImgPreview.hint": "برای آپلود، فایل خود را بکشید و در این نقطه رها کنید یا {browse}",
"app.components.ImgPreview.hint.browse": "مرور کردن",
"app.components.InputFile.newFile": "افزودن فایل جدید",
"app.components.InputFileDetails.open": "باز کردن در تب جدید",
"app.components.InputFileDetails.originalName": "نام اصلی:",
"app.components.InputFileDetails.remove": "حذف این فایل",
"app.components.InputFileDetails.size": "حجم:",
"app.components.InstallPluginPage.InputSearch.label": " ",
"app.components.InstallPluginPage.InputSearch.placeholder": "جستجوی افزونه... (برای مثال: authentication)",
"app.components.InstallPluginPage.description": "به راحتی برنامه خود را توسعه دهید.",
"app.components.InstallPluginPage.helmet": "فروشگاه - افزونه ها",
"app.components.InstallPluginPage.plugin.support-us.description": "با خرید تی شرت ما میتوانیم به توسعه Strapi ادامه داده و بهترین تجربه را برای شما فراهم کنیم!",
"app.components.InstallPluginPage.title": "فروشگاه - افزونه ها",
"app.components.InstallPluginPopup.downloads": "دانلود",
"app.components.InstallPluginPopup.navLink.avis": "مشاهده",
"app.components.InstallPluginPopup.navLink.changelog": "تغییرات",
"app.components.InstallPluginPopup.navLink.description": "توضیحات",
"app.components.InstallPluginPopup.navLink.faq": "پرسش و پاسخ",
"app.components.InstallPluginPopup.navLink.screenshots": "تصاویر",
"app.components.InstallPluginPopup.noDescription": "توضیحاتی وجود ندارد",
"app.components.LeftMenuFooter.poweredBy": "قدرت گرفته از ",
"app.components.LeftMenuLinkContainer.configuration": "پیکربندی",
"app.components.LeftMenuLinkContainer.general": "عمومی",
"app.components.LeftMenuLinkContainer.installNewPlugin": "فروشگاه",
"app.components.LeftMenuLinkContainer.listPlugins": "افزونه ها",
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "هیچ افزونه ای نصب نشده است",
"app.components.LeftMenuLinkContainer.plugins": "افزونه ها",
"app.components.ListPluginsPage.description": "فهرست افزونه های نصب شده در پروژه.",
"app.components.ListPluginsPage.helmet.title": "فهرست افزونه ها",
"app.components.ListPluginsPage.title": "افزونه ها",
"app.components.NotFoundPage.back": "بازگشت به صفحه اصلی",
"app.components.NotFoundPage.description": "یافت نشد",
"app.components.Official": "رسمی",
"app.components.PluginCard.Button.label.download": "دانلود",
"app.components.PluginCard.Button.label.install": "قبلا نصب شده است",
"app.components.PluginCard.Button.label.support": "حمایت از ما",
"app.components.PluginCard.compatible": "سازگار با برنامه ی شما",
"app.components.PluginCard.compatibleCommunity": "سازگار با جامعه ی توسعه دهنده",
"app.components.PluginCard.more-details": "اطلاعات بیشتر",
"app.components.PluginCard.price.free": "ریگان",
"app.components.listPlugins.button": "افزودن افزونه جدید",
"app.components.listPlugins.title.none": "هیچ افزونه ای نصب نشده است",
"app.components.listPlugins.title.plural": "{number} افزونه نصب شده",
"app.components.listPlugins.title.singular": "{number} افزونه نصب شده",
"app.components.listPluginsPage.deletePlugin.error": "خطا در هنگام حذف این افزونه",
"app.utils.SelectOption.defaultMessage": " ",
"app.utils.defaultMessage": " ",
"app.utils.placeholder.defaultMessage": " ",
"components.AutoReloadBlocker.description": "فایل را باز کرده و این ویژگی را فعال کنید.",
"components.AutoReloadBlocker.header": "بارگذاری مجدد برای این افزونه ضروری است.",
"components.ErrorBoundary.title": "خطایی رخ داده است...",
"components.Input.error.attribute.key.taken": "این مقدار در حال حاضر وجود دارد",
"components.Input.error.attribute.sameKeyAndName": "نمیتواند برابر باشد",
"components.Input.error.attribute.taken": "نام فیلد در حال حاضر وجود دارد",
"components.Input.error.contentTypeName.taken": "این نام هم اکنون وجود دارد",
"components.Input.error.custom-error": "{errorMessage} ",
"components.Input.error.validation.email": "این مقدار پست الکترونیک صحیح نیست",
"components.Input.error.validation.json": "این مقدار با فرمت استاندارد JSON مطابقت ندارد",
"components.Input.error.validation.max": "این مقدار زیاد است.",
"components.Input.error.validation.maxLength": "این مقدار طولانی است.",
"components.Input.error.validation.min": "این مقدار کوچک است.",
"components.Input.error.validation.minLength": "طول این مقدار کم است.",
"components.Input.error.validation.minSupMax": "نمی تواند بالاتر باشد",
"components.Input.error.validation.regex": "این مقدار با عبارت منظم مطابقت ندارد.",
"components.Input.error.validation.required": "این مقدار ضروری است.",
"components.ListRow.empty": "داده ای جهت نمایش وجود ندارد.",
"components.OverlayBlocker.description": "اقدام مورد نظر نیازمند راه اندازی مجدد سرور است. لطفا منتظر بمانید.",
"components.OverlayBlocker.title": "در انتظار راه اندازی مجدد...",
"components.PageFooter.select": "تعداد سطر در هر صفحه",
"components.ProductionBlocker.description": "به جهت موارد امنیتی ما باید این افزونه را در محیط های دیگر غیرفعال کنیم.",
"components.ProductionBlocker.header": "این افزونه فقط در حالت توسعه در دسترس است.",
"components.Wysiwyg.ToggleMode.markdown": "تبدیل به حالت markdown",
"components.Wysiwyg.ToggleMode.preview": "تبدیل به حالت نمایشی",
"components.Wysiwyg.collapse": "کوچک کردن",
"components.Wysiwyg.selectOptions.H1": "عنوان H1",
"components.Wysiwyg.selectOptions.H2": "عنوان H2",
"components.Wysiwyg.selectOptions.H3": "عنوان H3",
"components.Wysiwyg.selectOptions.H4": "عنوان H4",
"components.Wysiwyg.selectOptions.H5": "عنوان H5",
"components.Wysiwyg.selectOptions.H6": "عنوان H6",
"components.Wysiwyg.selectOptions.title": "افزدون عنوان",
"components.WysiwygBottomControls.charactersIndicators": "حروف",
"components.WysiwygBottomControls.fullscreen": "تمام صفحه",
"components.WysiwygBottomControls.uploadFiles": "کشیدن و رها کردن فایل، خواندن از حافظه یا {browse}.",
"components.WysiwygBottomControls.uploadFiles.browse": "انتخاب کنید",
"components.popUpWarning.button.cancel": "کنسل",
"components.popUpWarning.button.confirm": "تایید",
"components.popUpWarning.message": "آیا از حذف این مقدار اطمینان دارید؟",
"components.popUpWarning.title": "لطفا تایید کنید",
"notification.error": "خطایی رخ داده است",
"notification.error.layout": "خطا در بازیابی طرح",
"request.error.model.unknown": "این مدل وجود ندارد",
"app.utils.delete": "حذف"
}

View File

@ -28,8 +28,7 @@ module.exports = {
getGaConfig: async ctx => {
try {
const allowGa = _.get(strapi.config, 'info.customs.allowGa', true);
ctx.send({ allowGa });
ctx.send({ uuid: _.get(strapi.config, 'uuid', false) });
} catch(err) {
ctx.badRequest(null, [{ messages: [{ id: 'An error occurred' }] }]);
}

View File

@ -10,7 +10,7 @@ If you don't want to share your data with us, you can simply modify the `strapi`
```json
{
"strapi": {
"allowGa": false
"uuid": false
}
}
```

View File

@ -12,7 +12,15 @@ module.exports = {
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: async (model, response, options) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchCollection: async (model, columns, options) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchCollection: async (model, columns, options) => {},
// Before fetching a value.
// Fired before a `fetch` operation.
// beforeFetch: async (model, columns, options) => {},

View File

@ -242,13 +242,13 @@ module.exports = {
acc[current] = params.values[current];
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
// Records to add in the relation.
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
(a[this.primaryKey] || a).toString() === (b[this.primaryKey] || b).toString()
);
// Records to remove in the relation.
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
(a[this.primaryKey] || a).toString() === (b[this.primaryKey] || b).toString()
)
.filter(x => toAdd.find(y => x.id === y.id) === undefined);

View File

@ -8,7 +8,7 @@ import React from 'react';
import Select from 'react-select';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import { cloneDeep, isArray, isNull, isUndefined, get, findIndex, isEmpty } from 'lodash';
import { cloneDeep, includes, isArray, isNull, isUndefined, get, findIndex, isEmpty } from 'lodash';
// Utils.
import request from 'utils/request';
@ -103,6 +103,15 @@ class SelectMany extends React.PureComponent {
});
};
handleInputChange = (value) => {
const clonedOptions = this.state.options;
const filteredValues = clonedOptions.filter(data => includes(data.label, value));
if (filteredValues.length === 0) {
return this.getOptions(value);
}
}
handleChange = value => {
// Remove new added value from available option;
this.state.options = this.state.options.filter(el =>
@ -169,6 +178,7 @@ class SelectMany extends React.PureComponent {
id={this.props.relation.alias}
isLoading={this.state.isLoading}
onChange={this.handleChange}
onInputChange={this.handleInputChange}
onMenuScrollToBottom={this.handleBottomScroll}
options={this.state.options}
placeholder={<FormattedMessage id='content-manager.containers.Edit.addAnItem' />}

View File

@ -102,7 +102,7 @@ module.exports = async cb => {
disabled: false,
};
});
// Don't display fields that are hidden by default like the resetPasswordToken for the model user
_.unset(fields, fieldsToRemove);
schemaModel.attributes = _.omit(schemaModel.attributes, fieldsToRemove);
@ -339,16 +339,16 @@ module.exports = async cb => {
});
// Update other keys
sameApis.map(apiPath => {
sameApis.forEach(apiPath => {
// This doesn't keep the prevSettings for the relations, the user will have to reset it.
// We might have to improve this if we want the order of the relations to be kept
const keysToUpdate = ['relations', 'loadedModel', 'associations', 'attributes', ['editDisplay', 'relations']].map(key => apiPath.concat(key));
['relations', 'loadedModel', 'associations', 'attributes', ['editDisplay', 'relations']]
.map(key => apiPath.concat(key))
.forEach(keyPath => {
const newValue = _.get(schema.models, keyPath);
keysToUpdate.map(keyPath => {
const newValue = _.get(schema.models, keyPath);
_.set(prevSchema.models, keyPath, newValue);
});
_.set(prevSchema.models, keyPath, newValue);
});
});
// Special handler for the upload relations
@ -363,6 +363,7 @@ module.exports = async cb => {
});
await pluginStore.set({ key: 'schema', value: prevSchema });
} catch(err) {
console.log('error', err);
}

View File

@ -1,7 +1,8 @@
const _ = require('lodash');
/**
* Retrieve the path of each API
* @param {Object}} data
* @param {Object}} data
* @returns {Array} Array of API path ['plugins.upload.file', 'plugins.users-permissions.user', ...]
*/
const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
@ -10,8 +11,8 @@ const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
}
if (curr === 'plugins') {
Object.keys(data[curr]).map(plugin => {
Object.keys(data[curr][plugin]).map(api => {
Object.keys(data[curr]).forEach(plugin => {
Object.keys(data[curr][plugin]).forEach(api => {
acc = acc.concat([`${curr}.${plugin}.${api}`]);
});
});
@ -23,8 +24,8 @@ const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
/**
* Retrieve all the fields from an api
* @param {Object} data
* @param {Array} apis
* @param {Object} data
* @param {Array} apis
* @returns {Array} Array composed of fields path for instance : [['plugins.users-permissions.user.fields.username', 'plugins.users-permissions.user.fields.email', 'plugins.users-permissions.user.fields.password'], [...]]
*/
const getApisKeys = (data, apis) => apis.map(apiPath => {
@ -43,12 +44,12 @@ const getApisUploadRelations = (data, sameArray) => sameArray.map(apiPath => {
.filter(relationName => {
return _.get(data.models, [...relationPath, relationName, 'plugin' ]) === 'upload';
});
return relations.map(relation => `${apiPath.join('.')}.editDisplay.availableFields.${relation}`);
});
/**
*
*
* @param {String} attrPath
* @returns {Array}
*/

View File

@ -105,9 +105,9 @@ module.exports = {
_.set(schema, [...schemaPath, 'editDisplay', 'fields'], newList.toJS());
}
Object.keys(attributes).map(attribute => {
Object.keys(attributes).forEach(attribute => {
const appearances = _.get(attributes, [attribute, 'appearance'], {});
Object.keys(appearances).map(appearance => {
Object.keys(appearances).forEach(appearance => {
_.set(layout, ['attributes', attribute, 'appearance'], appearances[appearance] ? appearance : '' );
});

View File

@ -373,14 +373,14 @@ module.exports = {
source: association.plugin,
};
if (association.type === 'model') {
params.id = obj[association.alias];
} else {
// Get refering model.
const ref = association.plugin
? strapi.plugins[association.plugin].models[params.model]
: strapi.models[params.model];
// Get refering model.
const ref = association.plugin
? strapi.plugins[association.plugin].models[params.model]
: strapi.models[params.model];
if (association.type === 'model') {
params.id = _.get(obj, [association.alias, ref.primaryKey], obj[association.alias]);
} else {
// Apply optional arguments to make more precise nested request.
const convertedParams = strapi.utils.models.convertParams(
name,

View File

@ -8,7 +8,7 @@ export default function checkFormValidity(settingType, data, providerToEdit = ''
const isProviderEnabled = get(data, 'enabled');
const keys = providerToEdit === 'email' ? [] : ['key', 'secret'];
keys.map(key => {
keys.forEach(key => {
if (isProviderEnabled && isEmpty(get(data, key))) {
formErrors.push({ name: key, errors: [{ id: 'components.Input.error.validation.required' }] });
}
@ -16,9 +16,9 @@ export default function checkFormValidity(settingType, data, providerToEdit = ''
break;
}
case 'email-templates': {
Object.keys(data.options).map((value) => {
Object.keys(data.options).forEach((value) => {
if (isObject(data.options[value])) {
Object.keys(data.options[value]).map(subValue => {
Object.keys(data.options[value]).forEach(subValue => {
if (isEmpty(get(data, ['options', value, subValue]))) {
formErrors.push({ name: `options.${value}.${subValue}`, errors: [{ id: 'components.Input.error.validation.required' }] });
}

View File

@ -199,9 +199,9 @@ module.exports = {
const prefix = curr.config.prefix;
const path = prefix !== undefined ? `${prefix}${curr.path}` : `/${current}${curr.path}`;
_.set(curr, 'path', path);
return acc.concat(curr);
}, []);
}, []);
acc[current] = routes;
@ -221,7 +221,7 @@ module.exports = {
// Aggregate first level actions.
const appActions = Object.keys(strapi.api || {}).reduce((acc, api) => {
Object.keys(_.get(strapi.api[api], 'controllers', {}))
.map(controller => {
.forEach(controller => {
const actions = Object.keys(strapi.api[api].controllers[controller])
.filter(action => _.isFunction(strapi.api[api].controllers[controller][action]))
.map(action => `application.${controller}.${action.toLowerCase()}`);
@ -235,7 +235,7 @@ module.exports = {
// Aggregate plugins' actions.
const pluginsActions = Object.keys(strapi.plugins).reduce((acc, plugin) => {
Object.keys(strapi.plugins[plugin].controllers)
.map(controller => {
.forEach(controller => {
const actions = Object.keys(strapi.plugins[plugin].controllers[controller])
.filter(action => _.isFunction(strapi.plugins[plugin].controllers[controller][action]))
.map(action => `${plugin}.${controller}.${action.toLowerCase()}`);

View File

@ -368,7 +368,7 @@ const enableHookNestedDependencies = function (name, flattenHooksConfig, force =
});
return apiModelsUsed.length !== 0;
}) || 0; // Filter model with the right connector
}); // Filter model with the right connector
flattenHooksConfig[name] = {
enabled: force || modelsUsed.length > 0 // Will return false if there is no model, else true.