mirror of
https://github.com/strapi/strapi.git
synced 2025-11-03 03:17:11 +00:00
Merge branch 'v4/backend' into pluginAPI/loadPlugin
This commit is contained in:
commit
18da6e2188
@ -163,7 +163,7 @@ Before submitting an issue you need to make sure:
|
||||
- You have already searched for related [issues](https://github.com/strapi/strapi/issues), and found none open (if you found a related _closed_ issue, please link to it from your post).
|
||||
- You are not asking a question about how to use Strapi or about whether or not Strapi has a certain feature. For general help using Strapi, you may:
|
||||
- Refer to [the official Strapi documentation](https://strapi.io).
|
||||
- Ask a member of the community in the [Strapi Slack Community](https://slack.strapi.io/).
|
||||
- Ask a member of the community in the [Strapi Discord Community](https://discord.strapi.io/).
|
||||
- Ask a question on [our community forum](https://forum.strapi.io).
|
||||
- Your issue title is concise, on-topic and polite.
|
||||
- You can and do provide steps to reproduce your issue.
|
||||
|
||||
@ -5,7 +5,7 @@ services:
|
||||
image: postgres
|
||||
restart: always
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
- pgdata_test:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: strapi
|
||||
POSTGRES_PASSWORD: strapi
|
||||
@ -24,10 +24,10 @@ services:
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
MYSQL_ROOT_PASSWORD: strapi
|
||||
volumes:
|
||||
- mysqldata:/var/lib/mysql
|
||||
- mysqldata_test:/var/lib/mysql
|
||||
ports:
|
||||
- '3306:3306'
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
mysqldata:
|
||||
pgdata_test:
|
||||
mysqldata_test:
|
||||
|
||||
@ -10,7 +10,7 @@ const postgres = {
|
||||
client: 'postgres',
|
||||
connection: {
|
||||
database: 'strapi',
|
||||
username: 'strapi',
|
||||
user: 'strapi',
|
||||
password: 'strapi',
|
||||
port: 5432,
|
||||
host: 'localhost',
|
||||
@ -22,7 +22,7 @@ const mysql = {
|
||||
client: 'mysql',
|
||||
connection: {
|
||||
database: 'strapi',
|
||||
username: 'strapi',
|
||||
user: 'strapi',
|
||||
password: 'strapi',
|
||||
port: 3306,
|
||||
host: 'localhost',
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
"test:front:update:ce": "cross-env NODE_ENV=test IS_EE=false jest --config ./jest.config.front.js --u",
|
||||
"test:snyk": "snyk test",
|
||||
"test:unit": "jest --verbose",
|
||||
"test:e2e": "FORCE_COLOR=true jest --config jest.config.e2e.js --verbose --runInBand --testRunner=jest-circus/runner",
|
||||
"test:e2e": "FORCE_COLOR=true jest --config jest.config.e2e.js --verbose --runInBand --testRunner=jest-circus/runner --forceExit --detectOpenHandles",
|
||||
"test:generate-app": "node test/create-test-app.js",
|
||||
"doc:api": "node scripts/open-api/serve.js"
|
||||
},
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
"node-fetch": "^2.6.1",
|
||||
"ora": "5.4.0",
|
||||
"@strapi/generate-new": "3.6.6",
|
||||
"tar": "6.1.2"
|
||||
"tar": "6.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
|
||||
@ -33,10 +33,10 @@ const HeaderSearch = ({ label, queryParameter }) => {
|
||||
// Create a new search in order to remove the filters
|
||||
currentSearch = new URLSearchParams('');
|
||||
|
||||
// Keep the previous params _sort, pageSize, page
|
||||
// Keep the previous params sort, pageSize, page
|
||||
const pageSize = query.get('pageSize');
|
||||
const page = query.get('page');
|
||||
const _sort = query.get('_sort');
|
||||
const sort = query.get('sort');
|
||||
|
||||
if (page) {
|
||||
currentSearch.set('page', page);
|
||||
@ -46,8 +46,8 @@ const HeaderSearch = ({ label, queryParameter }) => {
|
||||
currentSearch.set('pageSize', pageSize);
|
||||
}
|
||||
|
||||
if (_sort) {
|
||||
currentSearch.set('_sort', _sort);
|
||||
if (sort) {
|
||||
currentSearch.set('sort', sort);
|
||||
}
|
||||
|
||||
currentSearch.set(queryParameter, encodeURIComponent(value));
|
||||
|
||||
@ -8,7 +8,7 @@ const ListItem = ({ onClick, selectedItem, label, value }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const handleClick = () => {
|
||||
onClick({ target: { name: '_sort', value } });
|
||||
onClick({ target: { name: 'sort', value } });
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -4,9 +4,9 @@ import { Carret, useTracking } from '@strapi/helper-plugin';
|
||||
import { useListView } from '../../../hooks';
|
||||
|
||||
const Header = ({ fieldSchema: { type }, metadatas: { label, sortable, mainField }, name }) => {
|
||||
const { _sort, firstSortableHeader, setQuery } = useListView();
|
||||
const { sort, firstSortableHeader, setQuery } = useListView();
|
||||
const { trackUsage } = useTracking();
|
||||
const [sortBy, sortOrder] = _sort.split(':');
|
||||
const [sortBy, sortOrder] = sort.split(':');
|
||||
|
||||
let sortField = name;
|
||||
let useRelation = false;
|
||||
@ -29,7 +29,7 @@ const Header = ({ fieldSchema: { type }, metadatas: { label, sortable, mainField
|
||||
}
|
||||
|
||||
setQuery({
|
||||
_sort: value,
|
||||
sort: value,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -151,12 +151,12 @@ const SettingsViewWrapper = ({
|
||||
kind,
|
||||
uid,
|
||||
} = modifiedData;
|
||||
const _sort = `${defaultSortBy}:${defaultSortOrder}`;
|
||||
const sort = `${defaultSortBy}:${defaultSortOrder}`;
|
||||
const goBackSearch = `${stringify(
|
||||
{
|
||||
page: 1,
|
||||
pageSize,
|
||||
_sort,
|
||||
sort,
|
||||
},
|
||||
{ encode: false }
|
||||
)}${pluginsQueryParams ? `&${pluginsQueryParams}` : ''}`;
|
||||
|
||||
@ -15,7 +15,7 @@ describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | selectors',
|
||||
{
|
||||
kind: 'collectionType',
|
||||
name: 'api::address.address',
|
||||
search: 'page=1&pageSize=50&_sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
title: 'Addresses',
|
||||
to: '/content-manager/collectionType/api::address.address',
|
||||
uid: 'api::address.address',
|
||||
@ -23,7 +23,7 @@ describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | selectors',
|
||||
{
|
||||
kind: 'collectionType',
|
||||
name: 'api::category.category',
|
||||
search: 'page=1&pageSize=50&_sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
title: 'Categories',
|
||||
to: '/content-manager/collectionType/api::category.category',
|
||||
uid: 'api::category.category',
|
||||
@ -36,7 +36,7 @@ describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | selectors',
|
||||
{
|
||||
kind: 'collectionType',
|
||||
name: 'api::address.address',
|
||||
search: 'page=1&pageSize=50&_sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
title: 'Addresses',
|
||||
to: '/content-manager/collectionType/api::address.address',
|
||||
uid: 'api::address.address',
|
||||
@ -44,7 +44,7 @@ describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | selectors',
|
||||
{
|
||||
kind: 'collectionType',
|
||||
name: 'api::category.category',
|
||||
search: 'page=1&pageSize=50&_sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr',
|
||||
title: 'Categories',
|
||||
to: '/content-manager/collectionType/api::category.category',
|
||||
uid: 'api::category.category',
|
||||
|
||||
@ -23,7 +23,7 @@ const generateLinks = (links, type, configurations = []) => {
|
||||
const searchParams = {
|
||||
page: 1,
|
||||
pageSize: currentContentTypeConfig.settings.pageSize,
|
||||
_sort: `${currentContentTypeConfig.settings.defaultSortBy}:${currentContentTypeConfig.settings.defaultSortOrder}`,
|
||||
sort: `${currentContentTypeConfig.settings.defaultSortBy}:${currentContentTypeConfig.settings.defaultSortOrder}`,
|
||||
};
|
||||
|
||||
search = stringify(searchParams, { encode: false });
|
||||
|
||||
@ -48,7 +48,7 @@ describe('ADMIN | LeftMenu | utils', () => {
|
||||
{
|
||||
to: '/content-manager/collectionType/api::address.address',
|
||||
isDisplayed: true,
|
||||
search: `page=1&pageSize=2&_sort=name:ASC`,
|
||||
search: `page=1&pageSize=2&sort=name:ASC`,
|
||||
permissions: [
|
||||
{
|
||||
action: 'plugin::content-manager.explorer.create',
|
||||
|
||||
@ -106,7 +106,7 @@ describe('checkPermissions', () => {
|
||||
subject: 'api::address.address',
|
||||
},
|
||||
],
|
||||
search: 'page=1&pageSize=10&_sort=name:ASC',
|
||||
search: 'page=1&pageSize=10&sort=name:ASC',
|
||||
},
|
||||
{
|
||||
destination: '/content-manager/collectionType/api::article.article',
|
||||
|
||||
@ -122,7 +122,7 @@ function ListView({
|
||||
return formatFiltersFromQuery(query);
|
||||
}, [query]);
|
||||
|
||||
const _sort = query._sort;
|
||||
const sort = query.sort;
|
||||
const _q = query._q || '';
|
||||
|
||||
const label = contentType.info.label;
|
||||
@ -382,7 +382,7 @@ function ListView({
|
||||
<>
|
||||
<ListViewProvider
|
||||
_q={_q}
|
||||
_sort={_sort}
|
||||
sort={sort}
|
||||
data={data}
|
||||
entriesToDelete={entriesToDelete}
|
||||
filters={filters}
|
||||
|
||||
@ -5,19 +5,19 @@ describe('buildQueryString', () => {
|
||||
const queryParams = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'name:ASC',
|
||||
sort: 'name:ASC',
|
||||
};
|
||||
|
||||
const queryString = buildQueryString(queryParams);
|
||||
|
||||
expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC');
|
||||
expect(queryString).toBe('?page=1&pageSize=10&sort=name:ASC');
|
||||
});
|
||||
|
||||
it('creates a valid query string with default params & plugin options', () => {
|
||||
const queryParams = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'name:ASC',
|
||||
sort: 'name:ASC',
|
||||
plugins: {
|
||||
i18n: { locale: 'en' },
|
||||
},
|
||||
@ -25,27 +25,27 @@ describe('buildQueryString', () => {
|
||||
|
||||
const queryString = buildQueryString(queryParams);
|
||||
|
||||
expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC&_locale=en');
|
||||
expect(queryString).toBe('?page=1&pageSize=10&sort=name:ASC&_locale=en');
|
||||
});
|
||||
|
||||
it('creates a valid query string with a _where clause', () => {
|
||||
const queryParams = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'name:ASC',
|
||||
sort: 'name:ASC',
|
||||
_where: [{ name: 'hello world' }],
|
||||
};
|
||||
|
||||
const queryString = buildQueryString(queryParams);
|
||||
|
||||
expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC&_where[0][name]=hello world');
|
||||
expect(queryString).toBe('?page=1&pageSize=10&sort=name:ASC&_where[0][name]=hello world');
|
||||
});
|
||||
|
||||
it('creates a valid query string with a _where and plugin options', () => {
|
||||
const queryParams = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'name:ASC',
|
||||
sort: 'name:ASC',
|
||||
_where: [{ name: 'hello world' }],
|
||||
plugins: {
|
||||
i18n: { locale: 'en' },
|
||||
@ -55,7 +55,7 @@ describe('buildQueryString', () => {
|
||||
const queryString = buildQueryString(queryParams);
|
||||
|
||||
expect(queryString).toBe(
|
||||
'?page=1&pageSize=10&_sort=name:ASC&_where[0][name]=hello world&_locale=en'
|
||||
'?page=1&pageSize=10&sort=name:ASC&_where[0][name]=hello world&_locale=en'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -30,7 +30,7 @@ const init = (initialState, settings) => {
|
||||
{
|
||||
intlLabel: { id: 'Settings.permissions.menu.link.users.label' },
|
||||
// Init the search params directly
|
||||
to: '/settings/users?pageSize=10&page=1&_sort=firstname%3AASC',
|
||||
to: '/settings/users?pageSize=10&page=1&sort=firstname',
|
||||
id: 'users',
|
||||
isDisplayed: false,
|
||||
permissions: adminPermissions.settings.users.main,
|
||||
|
||||
@ -11,7 +11,6 @@ const Wrapper = styled.div`
|
||||
padding: 8px 16px;
|
||||
|
||||
.bannerImage {
|
||||
margin-right: 1rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-right: 16px;
|
||||
|
||||
@ -50,7 +50,7 @@ const ListPage = () => {
|
||||
] = useReducer(reducer, initialState, init);
|
||||
const pageSize = parseInt(query.get('pageSize') || 10, 10);
|
||||
const page = parseInt(query.get('page') || 0, 10);
|
||||
const _sort = decodeURIComponent(query.get('_sort'));
|
||||
const sort = decodeURIComponent(query.get('sort'));
|
||||
const _q = decodeURIComponent(query.get('_q') || '');
|
||||
const getDataRef = useRef();
|
||||
const listRef = useRef();
|
||||
@ -242,7 +242,7 @@ const ListPage = () => {
|
||||
<>
|
||||
<BaselineAlignment top size="1px">
|
||||
<Flex flexWrap="wrap">
|
||||
<SortPicker onChange={handleChangeSort} value={_sort} />
|
||||
<SortPicker onChange={handleChangeSort} value={sort} />
|
||||
<Padded right size="10px" />
|
||||
<BaselineAlignment bottom size="6px">
|
||||
<FilterPicker onChange={handleChangeFilter} />
|
||||
|
||||
@ -3,24 +3,24 @@ const getFilters = search => {
|
||||
const filters = [];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (let pair of query.entries()) {
|
||||
if (!['_sort', 'pageSize', 'page', '_q'].includes(pair[0])) {
|
||||
const splitted = pair[0].split('_');
|
||||
for (let [key, queryValue] of query.entries()) {
|
||||
if (!['sort', 'pageSize', 'page', '_q'].includes(key)) {
|
||||
const splitted = key.split('_');
|
||||
let filterName;
|
||||
let filterType;
|
||||
|
||||
// Filter type === '=')
|
||||
if (splitted.length === 1) {
|
||||
filterType = '=';
|
||||
filterName = pair[0];
|
||||
filterName = key;
|
||||
} else {
|
||||
filterType = `_${splitted[1]}`;
|
||||
filterName = splitted[0];
|
||||
}
|
||||
|
||||
const value = decodeURIComponent(pair[1]);
|
||||
const value = decodeURIComponent(queryValue);
|
||||
|
||||
filters.push({ displayName: filterName, name: pair[0], filter: filterType, value });
|
||||
filters.push({ displayName: filterName, name: key, filter: filterType, value });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,13 +2,13 @@ import getFilters from '../getFilters';
|
||||
|
||||
describe('ADMIN | CONTAINERS | USERS | ListPage | utils | getFilters', () => {
|
||||
it('should return an empty array if there is not filter', () => {
|
||||
const search = '_q=test&_sort=firstname&page=1&pageSize=1';
|
||||
const search = '_q=test&sort=firstname&page=1&pageSize=1';
|
||||
|
||||
expect(getFilters(search)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle the = filter correctly ', () => {
|
||||
const search = '_sort=firstname&page=1&pageSize=1&firstname=test&firstname_ne=something';
|
||||
const search = 'sort=firstname&page=1&pageSize=1&firstname=test&firstname_ne=something';
|
||||
const expected = [
|
||||
{
|
||||
displayName: 'firstname',
|
||||
|
||||
@ -135,7 +135,7 @@ module.exports = {
|
||||
roles: superAdminRole ? [superAdminRole.id] : [],
|
||||
});
|
||||
|
||||
await strapi.telemetry.send('didCreateFirstAdmin');
|
||||
strapi.telemetry.send('didCreateFirstAdmin');
|
||||
|
||||
ctx.body = {
|
||||
data: {
|
||||
|
||||
@ -5,11 +5,11 @@ const { getService } = require('../utils');
|
||||
const sendDidInviteUser = async () => {
|
||||
const numberOfUsers = await getService('user').count();
|
||||
const numberOfRoles = await getService('role').count();
|
||||
return strapi.telemetry.send('didInviteUser', { numberOfRoles, numberOfUsers });
|
||||
strapi.telemetry.send('didInviteUser', { numberOfRoles, numberOfUsers });
|
||||
};
|
||||
|
||||
const sendDidUpdateRolePermissions = async () => {
|
||||
return strapi.telemetry.send('didUpdateRolePermissions');
|
||||
strapi.telemetry.send('didUpdateRolePermissions');
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@ -41,7 +41,7 @@ const create = async attributes => {
|
||||
.query('strapi::user')
|
||||
.create({ data: user, populate: ['roles'] });
|
||||
|
||||
await getService('metrics').sendDidInviteUser();
|
||||
getService('metrics').sendDidInviteUser();
|
||||
|
||||
return createdUser;
|
||||
};
|
||||
|
||||
@ -62,6 +62,8 @@ module.exports = {
|
||||
const { model } = ctx.params;
|
||||
const { body } = ctx.request;
|
||||
|
||||
const totalEntries = await strapi.query(model).count();
|
||||
|
||||
const entityManager = getService('entity-manager');
|
||||
const permissionChecker = getService('permission-checker').create({ userAbility, model });
|
||||
|
||||
@ -77,9 +79,12 @@ module.exports = {
|
||||
|
||||
await wrapBadRequest(async () => {
|
||||
const entity = await entityManager.create(sanitizeFn(body), model);
|
||||
|
||||
ctx.body = permissionChecker.sanitizeOutput(entity);
|
||||
|
||||
await strapi.telemetry.send('didCreateFirstContentTypeEntry', { model });
|
||||
if (totalEntries === 0) {
|
||||
strapi.telemetry.send('didCreateFirstContentTypeEntry', { model });
|
||||
}
|
||||
})();
|
||||
},
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const createLifecyclesManager = db => {
|
||||
let subscribers = [];
|
||||
|
||||
const lifecycleManager = {
|
||||
_subscribers: [],
|
||||
subscribe(subscriber) {
|
||||
// TODO: verify subscriber
|
||||
|
||||
this._subscribers.push(subscriber);
|
||||
subscribers.push(subscriber);
|
||||
|
||||
return () => {
|
||||
this._subscribers.splice(this._subscribers.indexOf(subscriber), 1);
|
||||
subscribers.splice(subscribers.indexOf(subscriber), 1);
|
||||
};
|
||||
},
|
||||
|
||||
@ -24,10 +24,11 @@ const createLifecyclesManager = db => {
|
||||
},
|
||||
|
||||
async run(action, uid, properties) {
|
||||
for (const subscriber of this._subscribers) {
|
||||
for (const subscriber of subscribers) {
|
||||
if (typeof subscriber === 'function') {
|
||||
const event = this.createEvent(action, uid, properties);
|
||||
return await subscriber(event);
|
||||
await subscriber(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
const hasAction = action in subscriber;
|
||||
@ -42,7 +43,7 @@ const createLifecyclesManager = db => {
|
||||
},
|
||||
|
||||
clear() {
|
||||
this._subscribers = [];
|
||||
subscribers = [];
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -516,6 +516,10 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
const { db, uid, qb } = ctx;
|
||||
const meta = db.metadata.get(uid);
|
||||
|
||||
if (_.isEmpty(results)) {
|
||||
return results;
|
||||
}
|
||||
|
||||
for (const key in populate) {
|
||||
// NOTE: Omit limit & offset to avoid needing a query per result to avoid making too many queries
|
||||
const populateValue = _.pick(
|
||||
@ -579,34 +583,16 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
} = joinTable.joinColumn;
|
||||
|
||||
const alias = qb.getAlias();
|
||||
const joinColAlias = `${alias}.${joinColumnName}`;
|
||||
|
||||
if (isCount) {
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
alias: alias,
|
||||
referencedTable: joinTable.name,
|
||||
referencedColumn: joinTable.inverseJoinColumn.name,
|
||||
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.select([`${alias}.${joinColumnName}`, qb.raw('count(*) AS count')])
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.groupBy(`${alias}.${joinColumnName}`)
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = rows.reduce((map, row) => {
|
||||
map[row[joinColumnName]] = { count: row.count };
|
||||
return map;
|
||||
}, {});
|
||||
const referencedValues = _.uniq(
|
||||
results.map(r => r[referencedColumnName]).filter(value => !_.isNil(value))
|
||||
);
|
||||
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach(result => {
|
||||
result[key] = map[result[referencedColumnName]] || { count: 0 };
|
||||
result[key] = null;
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -620,10 +606,8 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.addSelect(`${alias}.${joinColumnName}`)
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.addSelect(joinColAlias)
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = _.groupBy(joinColumnName, rows);
|
||||
@ -681,8 +665,20 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
} = joinTable.joinColumn;
|
||||
|
||||
const alias = qb.getAlias();
|
||||
const joinColAlias = `${alias}.${joinColumnName}`;
|
||||
|
||||
const referencedValues = _.uniq(
|
||||
results.map(r => r[referencedColumnName]).filter(value => !_.isNil(value))
|
||||
);
|
||||
|
||||
if (isCount) {
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach(result => {
|
||||
result[key] = { count: 0 };
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
@ -693,11 +689,9 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.select([`${alias}.${joinColumnName}`, qb.raw('count(*) AS count')])
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.groupBy(`${alias}.${joinColumnName}`)
|
||||
.select([joinColAlias, qb.raw('count(*) AS count')])
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.groupBy(joinColAlias)
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = rows.reduce((map, row) => {
|
||||
@ -712,6 +706,13 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach(result => {
|
||||
result[key] = [];
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
@ -722,10 +723,8 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.addSelect(`${alias}.${joinColumnName}`)
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.addSelect(joinColAlias)
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = _.groupBy(joinColumnName, rows);
|
||||
@ -745,8 +744,19 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
||||
|
||||
const alias = qb.getAlias();
|
||||
const joinColAlias = `${alias}.${joinColumnName}`;
|
||||
const referencedValues = _.uniq(
|
||||
results.map(r => r[referencedColumnName]).filter(value => !_.isNil(value))
|
||||
);
|
||||
|
||||
if (isCount) {
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach(result => {
|
||||
result[key] = { count: 0 };
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
@ -757,11 +767,9 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.select([`${alias}.${joinColumnName}`, qb.raw('count(*) AS count')])
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.groupBy(`${alias}.${joinColumnName}`)
|
||||
.select([joinColAlias, qb.raw('count(*) AS count')])
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.groupBy(joinColAlias)
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = rows.reduce((map, row) => {
|
||||
@ -776,6 +784,13 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_.isEmpty(referencedValues)) {
|
||||
results.forEach(result => {
|
||||
result[key] = [];
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const rows = await qb
|
||||
.init(populateValue)
|
||||
.join({
|
||||
@ -786,10 +801,8 @@ const applyPopulate = async (results, populate, ctx) => {
|
||||
rootTable: qb.alias,
|
||||
on: joinTable.on,
|
||||
})
|
||||
.addSelect(`${alias}.${joinColumnName}`)
|
||||
.where({
|
||||
[`${alias}.${joinColumnName}`]: results.map(r => r[referencedColumnName]),
|
||||
})
|
||||
.addSelect(joinColAlias)
|
||||
.where({ [joinColAlias]: referencedValues })
|
||||
.execute({ mapResults: false });
|
||||
|
||||
const map = _.groupBy(joinColumnName, rows);
|
||||
|
||||
@ -30,6 +30,13 @@ const createQueryBuilder = (uid, db) => {
|
||||
alias: getAlias(),
|
||||
getAlias,
|
||||
|
||||
select(args) {
|
||||
state.type = 'select';
|
||||
state.select = _.castArray(args).map(col => this.aliasColumn(col));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
insert(data) {
|
||||
state.type = 'insert';
|
||||
state.data = data;
|
||||
@ -65,13 +72,6 @@ const createQueryBuilder = (uid, db) => {
|
||||
return this;
|
||||
},
|
||||
|
||||
select(args) {
|
||||
state.type = 'select';
|
||||
state.select = _.castArray(args).map(col => this.aliasColumn(col));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addSelect(args) {
|
||||
state.select.push(..._.castArray(args).map(col => this.aliasColumn(col)));
|
||||
return this;
|
||||
|
||||
@ -72,13 +72,18 @@ module.exports = db => ({
|
||||
await db.connection.transaction(async trx => {
|
||||
await this.createTables(schemaDiff.tables.added, trx);
|
||||
|
||||
// TODO: drop foreign keys targeting delete tables
|
||||
// drop all delete table foreign keys then delete the tables
|
||||
for (const table of schemaDiff.tables.removed) {
|
||||
debug(`Removing table foreign keys: ${table.name}`);
|
||||
|
||||
const schemaBuilder = this.getSchemaBuilder(table, trx);
|
||||
await dropTableForeignKeys(schemaBuilder, table);
|
||||
}
|
||||
|
||||
for (const table of schemaDiff.tables.removed) {
|
||||
debug(`Removing table: ${table.name}`);
|
||||
|
||||
const schemaBuilder = this.getSchemaBuilder(table, trx);
|
||||
// TODO: add cascading if possible
|
||||
await dropTable(schemaBuilder, table);
|
||||
}
|
||||
|
||||
@ -288,6 +293,8 @@ const dropColumn = (tableBuilder, column) => {
|
||||
const createTable = async (schemaBuilder, table) => {
|
||||
if (await schemaBuilder.hasTable(table.name)) {
|
||||
throw new Error(`Table already exists ${table.name}`);
|
||||
|
||||
// TODO: alter the table instead
|
||||
}
|
||||
|
||||
await schemaBuilder.createTable(table.name, tableBuilder => {
|
||||
@ -299,6 +306,13 @@ const createTable = async (schemaBuilder, table) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Drops a table from a database
|
||||
* @param {Knex.SchemaBuilder} schemaBuilder
|
||||
* @param {Table} table
|
||||
*/
|
||||
const dropTable = (schemaBuilder, table) => schemaBuilder.dropTableIfExists(table.name);
|
||||
|
||||
/**
|
||||
* Creates a table foreign keys constraints
|
||||
* @param {SchemaBuilder} schemaBuilder
|
||||
@ -312,8 +326,13 @@ const createTableForeignKeys = async (schemaBuilder, table) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Drops a table from a database
|
||||
* @param {Knex.SchemaBuilder} schemaBuilder
|
||||
* Drops a table foreign keys constraints
|
||||
* @param {SchemaBuilder} schemaBuilder
|
||||
* @param {Table} table
|
||||
*/
|
||||
const dropTable = (schemaBuilder, table) => schemaBuilder.dropTableIfExists(table.name);
|
||||
const dropTableForeignKeys = async (schemaBuilder, table) => {
|
||||
// foreign keys
|
||||
await schemaBuilder.table(table.name, tableBuilder => {
|
||||
(table.foreignKeys || []).forEach(foreignKey => dropForeignKey(tableBuilder, foreignKey));
|
||||
});
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@ const generateFiltersFromSearch = search => {
|
||||
x =>
|
||||
!x.includes('_limit') &&
|
||||
!x.includes('_page') &&
|
||||
!x.includes('_sort') &&
|
||||
!x.includes('sort') &&
|
||||
!x.includes('_start') &&
|
||||
!x.includes('_q=') &&
|
||||
x !== ''
|
||||
|
||||
@ -3,7 +3,7 @@ import generateFiltersFromSearch from '../generateFiltersFromSearch';
|
||||
describe('HELPER PLUGIN | utils | generateFiltersFromSearch', () => {
|
||||
it('should generate an array of filters', () => {
|
||||
const search =
|
||||
'?_sort=id:ASC&bool=true&big_number_ne=1&created_at_lt=2019-08-01T00:00:00Z&date_lte=2019-08-02T00:00:00Z&decimal_number_gt=2&enum_ne=noon&float_number_gte=3';
|
||||
'?sort=id:ASC&bool=true&big_number_ne=1&created_at_lt=2019-08-01T00:00:00Z&date_lte=2019-08-02T00:00:00Z&decimal_number_gt=2&enum_ne=noon&float_number_gte=3';
|
||||
const expected = [
|
||||
{
|
||||
name: 'bool',
|
||||
|
||||
@ -4,7 +4,7 @@ describe('HELPER PLUGIN | utils | generateSearchFromFilters', () => {
|
||||
it('should return a string with all the applied filters', () => {
|
||||
const data = {
|
||||
_limit: 10,
|
||||
_sort: 'id:ASC',
|
||||
sort: 'id:ASC',
|
||||
_page: 2,
|
||||
filters: [
|
||||
{
|
||||
@ -46,7 +46,7 @@ describe('HELPER PLUGIN | utils | generateSearchFromFilters', () => {
|
||||
};
|
||||
|
||||
const expected =
|
||||
'_limit=10&_sort=id:ASC&_page=2&bool=true&big_number_ne=1&created_at_lt=2019-08-01T00:00:00Z&date_lte=2019-08-02T00:00:00Z&decimal_number_gt=2&enum_ne=noon&float_number_gte=3';
|
||||
'_limit=10&sort=id:ASC&_page=2&bool=true&big_number_ne=1&created_at_lt=2019-08-01T00:00:00Z&date_lte=2019-08-02T00:00:00Z&decimal_number_gt=2&enum_ne=noon&float_number_gte=3';
|
||||
const encoded = expected
|
||||
.split('&')
|
||||
.map(pair => {
|
||||
|
||||
@ -2,15 +2,15 @@ import generateSearchFromObject from '../generateSearchFromObject';
|
||||
|
||||
describe('HELPER PLUGIN | utils | generateSearchFromObject', () => {
|
||||
it('should return a string containing the _limit, _start and order', () => {
|
||||
const search = { _page: 1, _limit: 10, _sort: 'city:ASC' };
|
||||
const expected = '_limit=10&_sort=city:ASC&_start=0';
|
||||
const search = { _page: 1, _limit: 10, sort: 'city:ASC' };
|
||||
const expected = '_limit=10&sort=city:ASC&_start=0';
|
||||
|
||||
expect(generateSearchFromObject(search)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should remove the _q param from the search if it is empty', () => {
|
||||
const search = { _page: 1, _limit: 10, _sort: 'city:ASC', _q: '' };
|
||||
const expected = '_limit=10&_sort=city:ASC&_start=0';
|
||||
const search = { _page: 1, _limit: 10, sort: 'city:ASC', _q: '' };
|
||||
const expected = '_limit=10&sort=city:ASC&_start=0';
|
||||
|
||||
expect(generateSearchFromObject(search)).toEqual(expected);
|
||||
});
|
||||
@ -19,11 +19,11 @@ describe('HELPER PLUGIN | utils | generateSearchFromObject', () => {
|
||||
const search = {
|
||||
_page: 1,
|
||||
_limit: 10,
|
||||
_sort: 'city:ASC',
|
||||
sort: 'city:ASC',
|
||||
_q: '',
|
||||
filters: [],
|
||||
};
|
||||
const expected = '_limit=10&_sort=city:ASC&_start=0';
|
||||
const expected = '_limit=10&sort=city:ASC&_start=0';
|
||||
|
||||
expect(generateSearchFromObject(search)).toEqual(expected);
|
||||
});
|
||||
@ -33,11 +33,11 @@ describe('HELPER PLUGIN | utils | generateSearchFromObject', () => {
|
||||
_limit: 10,
|
||||
_page: 1,
|
||||
_q: '',
|
||||
_sort: 'city:ASC',
|
||||
sort: 'city:ASC',
|
||||
filters: [{ name: 'city', filter: '=', value: 'test' }],
|
||||
};
|
||||
|
||||
const expected = '_limit=10&_sort=city:ASC&city=test&_start=0';
|
||||
const expected = '_limit=10&sort=city:ASC&city=test&_start=0';
|
||||
|
||||
expect(generateSearchFromObject(search)).toEqual(expected);
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
const path = require('path');
|
||||
const createMiddleware = require('../index');
|
||||
const configProvider = require('../../../core/base-providers/config-provider');
|
||||
const configProvider = require('../../../core/registries/config');
|
||||
|
||||
describe('Session middleware', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@ -134,7 +134,7 @@ const BrowseAssets = () => {
|
||||
/>
|
||||
</Padded>
|
||||
)}
|
||||
<SortPicker onChange={handleChangeParams} value={params._sort} />
|
||||
<SortPicker onChange={handleChangeParams} value={params.sort} />
|
||||
<Padded left size="sm" />
|
||||
<Filters
|
||||
filters={params.filters}
|
||||
|
||||
@ -6,41 +6,17 @@
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import get from 'lodash/get';
|
||||
import { request, useNotification } from '@strapi/helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
import { setFileModelTimestamps } from './actions';
|
||||
|
||||
// TODO use the models API and remove this component
|
||||
const Initializer = ({ setPlugin }) => {
|
||||
const ref = useRef();
|
||||
const dispatch = useDispatch();
|
||||
ref.current = setPlugin;
|
||||
const toggleNotification = useNotification();
|
||||
|
||||
// TODO: remove
|
||||
useEffect(() => {
|
||||
const getData = async () => {
|
||||
const requestURL = '/content-manager/content-types';
|
||||
|
||||
try {
|
||||
const { data } = await request(requestURL, { method: 'GET' });
|
||||
const fileModel = data.find(model => model.uid === 'plugin::upload.file');
|
||||
const timestamps = get(fileModel, ['options', 'timestamps']);
|
||||
|
||||
dispatch(setFileModelTimestamps(timestamps));
|
||||
|
||||
ref.current(pluginId);
|
||||
} catch (err) {
|
||||
toggleNotification({
|
||||
type: 'warning',
|
||||
message: { id: 'content-manager.error.model.fetch' },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getData();
|
||||
}, [dispatch, toggleNotification]);
|
||||
ref.current(pluginId);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -2,7 +2,8 @@ import produce from 'immer';
|
||||
import { SET_FILE_MODE_TIMESTAMPS } from './constants';
|
||||
|
||||
const initialState = {
|
||||
fileModelTimestamps: [],
|
||||
// TODO: rename to camelCase
|
||||
fileModelTimestamps: ['created_at', 'updated_at'],
|
||||
};
|
||||
|
||||
const reducer = (state = initialState, action) =>
|
||||
@ -10,7 +11,7 @@ const reducer = (state = initialState, action) =>
|
||||
produce(state, draftState => {
|
||||
switch (action.type) {
|
||||
case SET_FILE_MODE_TIMESTAMPS: {
|
||||
draftState.fileModelTimestamps = action.timestamps;
|
||||
// draftState.fileModelTimestamps = action.timestamps;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@ -64,7 +64,7 @@ const InputModalStepperProvider = ({
|
||||
: [],
|
||||
params: {
|
||||
...state.params,
|
||||
_sort: `${updated_at}:DESC`,
|
||||
sort: `${updated_at}:DESC`,
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -336,7 +336,7 @@ const InputModalStepperProvider = ({
|
||||
|
||||
const fetchMediaLibFilesCount = async () => {
|
||||
const requestURL = getRequestUrl('files/count');
|
||||
const paramsToSend = getFilters(['_limit', '_sort', '_start']);
|
||||
const paramsToSend = getFilters(['_limit', '_start']);
|
||||
|
||||
try {
|
||||
return await request(`${requestURL}?${paramsToSend}`, {
|
||||
|
||||
@ -21,7 +21,7 @@ const initialState = {
|
||||
_start: 0,
|
||||
_q: '',
|
||||
filters: [],
|
||||
_sort: null,
|
||||
sort: null,
|
||||
},
|
||||
currentStep: 'list',
|
||||
isFormDisabled: false,
|
||||
@ -180,7 +180,7 @@ const reducer = (state, action) =>
|
||||
}
|
||||
case 'RESET_PROPS': {
|
||||
if (action.defaultSort) {
|
||||
draftState.params._sort = action.defaultSort;
|
||||
draftState.params.sort = action.defaultSort;
|
||||
} else {
|
||||
return initialState;
|
||||
}
|
||||
|
||||
@ -1725,7 +1725,7 @@ describe('UPLOAD | components | InputModalStepperProvider | reducer', () => {
|
||||
_start: 0,
|
||||
_q: '',
|
||||
filters: [],
|
||||
_sort: null,
|
||||
sort: null,
|
||||
},
|
||||
currentStep: 'list',
|
||||
isFormDisabled: false,
|
||||
|
||||
@ -8,7 +8,7 @@ import IntlText from '../IntlText';
|
||||
|
||||
const SortListItem = ({ onClick, selectedItem, label, value }) => {
|
||||
const handleClick = () => {
|
||||
onClick({ target: { name: '_sort', value } });
|
||||
onClick({ target: { name: 'sort', value } });
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -72,7 +72,7 @@ const HomePageSettings = ({
|
||||
<Padded right />
|
||||
</>
|
||||
)}
|
||||
<SortPicker onChange={onChange} value={query.get('_sort') || `${updated_at}:DESC`} />
|
||||
<SortPicker onChange={onChange} value={query.get('sort') || `${updated_at}:DESC`} />
|
||||
<Padded right />
|
||||
<Filters onChange={onChange} filters={filters} onClick={onFilterDelete} />
|
||||
</ControlsWrapper>
|
||||
|
||||
@ -42,7 +42,7 @@ const HomePage = () => {
|
||||
const isMounted = useRef(true);
|
||||
|
||||
const pluginName = formatMessage({ id: getTrad('plugin.name') });
|
||||
const paramsKeys = ['_limit', '_start', '_q', '_sort'];
|
||||
const paramsKeys = ['_limit', '_start', '_q', 'sort'];
|
||||
|
||||
useEffect(() => {
|
||||
return () => (isMounted.current = false);
|
||||
@ -74,9 +74,9 @@ const HomePage = () => {
|
||||
const dataRequestURL = getRequestUrl('files');
|
||||
const params = generateStringFromParams(query);
|
||||
|
||||
const paramsToSend = params.includes('_sort')
|
||||
const paramsToSend = params.includes('sort')
|
||||
? params
|
||||
: params.concat(`&_sort=${updated_at}:DESC`);
|
||||
: params.concat(`&sort=${updated_at}:DESC`);
|
||||
|
||||
try {
|
||||
const data = await request(`${dataRequestURL}?${paramsToSend}`, {
|
||||
@ -98,7 +98,7 @@ const HomePage = () => {
|
||||
};
|
||||
|
||||
const fetchDataCount = async () => {
|
||||
const params = generateStringFromParams(query, ['_limit', '_sort', '_start']);
|
||||
const params = generateStringFromParams(query, ['_limit', '_start']);
|
||||
const requestURL = getRequestUrl('files/count');
|
||||
|
||||
try {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const MANY_RELATIONS = ['oneToMany', 'manyToMany', 'manyWay'];
|
||||
const MANY_RELATIONS = ['oneToMany', 'manyToMany'];
|
||||
|
||||
const getRelationalFields = contentType => {
|
||||
return Object.keys(contentType.attributes).filter(attributeName => {
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-machine-id": "^1.1.10",
|
||||
"ora": "^5.4.0",
|
||||
"tar": "6.1.2",
|
||||
"tar": "6.1.4",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -35,7 +35,7 @@ describe('dataloader', () => {
|
||||
test('makeQuery calls find', async () => {
|
||||
const uid = 'uid';
|
||||
const find = jest.fn(() => [{ id: 1 }]);
|
||||
const filters = { _limit: 5, _sort: 'field' };
|
||||
const filters = { limit: 5, sort: 'field' };
|
||||
|
||||
global.strapi = {
|
||||
query() {
|
||||
|
||||
@ -5,7 +5,7 @@ describe('getInitialLocale', () => {
|
||||
const query = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'Name:ASC',
|
||||
sort: 'Name:ASC',
|
||||
plugins: {
|
||||
i18n: { locale: 'fr-FR' },
|
||||
},
|
||||
@ -47,7 +47,7 @@ describe('getInitialLocale', () => {
|
||||
const query = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'Name:ASC',
|
||||
sort: 'Name:ASC',
|
||||
plugins: {
|
||||
something: 'great',
|
||||
},
|
||||
@ -90,7 +90,7 @@ describe('getInitialLocale', () => {
|
||||
const query = {
|
||||
page: '1',
|
||||
pageSize: '10',
|
||||
_sort: 'Name:ASC',
|
||||
sort: 'Name:ASC',
|
||||
plugins: {
|
||||
something: 'great',
|
||||
},
|
||||
|
||||
@ -81,6 +81,12 @@ describe('i18n - Relation-list route', () => {
|
||||
beforeAll(async () => {
|
||||
await builder
|
||||
.addContentTypes([productModel, shopModel])
|
||||
.addFixtures('plugin::i18n.locale', [
|
||||
{
|
||||
name: 'It',
|
||||
code: 'it',
|
||||
},
|
||||
])
|
||||
.addFixtures(shopModel.name, shops)
|
||||
.addFixtures(productModel.name, products)
|
||||
.build();
|
||||
|
||||
@ -26,7 +26,7 @@ const createTestBuilder = (options = {}) => {
|
||||
},
|
||||
|
||||
sanitizedFixturesFor(modelName, strapi) {
|
||||
const model = strapi.getModel(`application::${modelName}.${modelName}`);
|
||||
const model = strapi.getModel(modelsUtils.toUID(modelName));
|
||||
const fixtures = this.fixturesFor(modelName);
|
||||
|
||||
return sanitizeEntity(fixtures, { model });
|
||||
|
||||
@ -3,6 +3,10 @@
|
||||
const { isFunction, isNil, prop } = require('lodash/fp');
|
||||
const { createStrapiInstance } = require('./strapi');
|
||||
|
||||
const toUID = name => {
|
||||
return name.includes('::') ? name : `application::${name}.${name}`;
|
||||
};
|
||||
|
||||
const createHelpers = async ({ strapi: strapiInstance = null, ...options } = {}) => {
|
||||
const strapi = strapiInstance || (await createStrapiInstance(options));
|
||||
const contentTypeService = strapi.plugins['content-type-builder'].services['content-types'];
|
||||
@ -141,7 +145,7 @@ async function createFixtures(dataMap, { strapi: strapiIst } = {}) {
|
||||
const entries = [];
|
||||
|
||||
for (const data of dataMap[model]) {
|
||||
entries.push(await strapi.query(`application::${model}.${model}`).create({ data }));
|
||||
entries.push(await strapi.entityService.create(toUID(model), { data }));
|
||||
}
|
||||
|
||||
resultMap[model] = entries;
|
||||
@ -158,9 +162,7 @@ async function createFixturesFor(model, entries, { strapi: strapiIst } = {}) {
|
||||
|
||||
for (const entry of entries) {
|
||||
const dataToCreate = isFunction(entry) ? entry(results) : entry;
|
||||
results.push(
|
||||
await strapi.query(`application::${model}.${model}`).create({ data: dataToCreate })
|
||||
);
|
||||
results.push(await strapi.entityService.create(toUID(model), { data: dataToCreate }));
|
||||
}
|
||||
|
||||
await cleanup();
|
||||
@ -171,9 +173,7 @@ async function createFixturesFor(model, entries, { strapi: strapiIst } = {}) {
|
||||
async function deleteFixturesFor(model, entries, { strapi: strapiIst } = {}) {
|
||||
const { strapi, cleanup } = await createHelpers({ strapi: strapiIst });
|
||||
|
||||
await strapi
|
||||
.query(`application::${model}.${model}`)
|
||||
.delete({ where: { id: entries.map(prop('id')) } });
|
||||
await strapi.query(toUID(model)).deleteMany({ where: { id: entries.map(prop('id')) } });
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
@ -185,7 +185,7 @@ async function modifyContentType(data, { strapi } = {}) {
|
||||
delete sanitizedData.editable;
|
||||
delete sanitizedData.restrictRelationsTo;
|
||||
|
||||
const uid = `application::${sanitizedData.name}.${sanitizedData.name}`;
|
||||
const uid = toUID(sanitizedData.name);
|
||||
|
||||
const ct = await contentTypeService.editContentType(uid, {
|
||||
contentType: {
|
||||
@ -201,7 +201,7 @@ async function modifyContentType(data, { strapi } = {}) {
|
||||
async function getContentTypeSchema(modelName, { strapi: strapiIst } = {}) {
|
||||
const { strapi, contentTypeService, cleanup } = await createHelpers({ strapi: strapiIst });
|
||||
|
||||
const uid = `application::${modelName}.${modelName}`;
|
||||
const uid = toUID(modelName);
|
||||
const ct = contentTypeService.formatContentType(strapi.contentTypes[uid]);
|
||||
|
||||
await cleanup();
|
||||
@ -210,6 +210,7 @@ async function getContentTypeSchema(modelName, { strapi: strapiIst } = {}) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toUID,
|
||||
// Create Content-Types
|
||||
createContentType,
|
||||
createContentTypes,
|
||||
|
||||
@ -20172,10 +20172,10 @@ tar-stream@^2.0.1, tar-stream@^2.1.0, tar-stream@^2.1.4, tar-stream@^2.2.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@6.1.2:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.2.tgz#1f045a90a6eb23557a603595f41a16c57d47adc6"
|
||||
integrity sha512-EwKEgqJ7nJoS+s8QfLYVGMDmAsj+StbI2AM/RTHeUSsOw6Z8bwNBRv5z3CY0m7laC5qUAqruLX5AhMuc5deY3Q==
|
||||
tar@6.1.4:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.4.tgz#9f0722b772a5e00dba7d52e1923b37a7ec3799b3"
|
||||
integrity sha512-kcPWrO8S5ABjuZ/v1xQHP8xCEvj1dQ1d9iAb6Qs4jLYzaAIYWwST2IQpz7Ud8VNYRI+fGhFjrnzRKmRggKWg3g==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user