diff --git a/packages/strapi-plugin-content-manager/admin/src/components/DragLayer/index.js b/packages/strapi-plugin-content-manager/admin/src/components/DragLayer/index.js
index 32f4effda2..305c8ed9e6 100644
--- a/packages/strapi-plugin-content-manager/admin/src/components/DragLayer/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/components/DragLayer/index.js
@@ -68,6 +68,7 @@ const CustomDragLayer = () => {
{
if (action.value && action.value._isAMomentObject === true) {
- return moment(action.value, 'YYYY-MM-DD HH:mm:ss').format();
+ return action.value.toISOString();
}
return action.value;
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js
index fba48296e3..5ea71aced0 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js
@@ -382,7 +382,7 @@ function ListView({
- {filters.map(({ filter: filterName, name }, key) => (
+ {filters.map(({ filter: filterName, name, value }, key) => (
))}
>
diff --git a/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/formatLayouts.js b/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/formatLayouts.js
index da4294ee11..68f0c88c58 100644
--- a/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/formatLayouts.js
+++ b/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/formatLayouts.js
@@ -2,6 +2,53 @@ import { cloneDeep, get, set } from 'lodash';
import { mergeMetasWithSchema } from '../../../utils';
import pluginId from '../../../pluginId';
+// editRelations is an array of strings...
+const formatEditRelationsLayoutWithMetas = (obj, models) => {
+ const formatted = obj.layouts.editRelations.reduce((acc, current) => {
+ const fieldSchema = get(obj, ['attributes', current], {});
+ const metadatas = get(obj, ['metadatas', current, 'edit'], {});
+ const size = 6;
+
+ const queryInfos = generateRelationQueryInfos(obj, current, models);
+
+ acc.push({
+ name: current,
+ size,
+ fieldSchema,
+ metadatas,
+ queryInfos,
+ });
+
+ return acc;
+ }, []);
+
+ return formatted;
+};
+
+const formatLayouts = (initialData, models) => {
+ const data = mergeMetasWithSchema(cloneDeep(initialData), models, 'contentType');
+ const formattedCTEditLayout = formatLayoutWithMetas(data.contentType, null, models);
+ const ctUid = data.contentType.uid;
+ const formattedEditRelationsLayout = formatEditRelationsLayoutWithMetas(data.contentType, models);
+ const formattedListLayout = formatListLayoutWithMetas(data.contentType);
+
+ set(data, ['contentType', 'layouts', 'edit'], formattedCTEditLayout);
+ set(data, ['contentType', 'layouts', 'editRelations'], formattedEditRelationsLayout);
+ set(data, ['contentType', 'layouts', 'list'], formattedListLayout);
+
+ Object.keys(data.components).forEach(compoUID => {
+ const formattedCompoEditLayout = formatLayoutWithMetas(
+ data.components[compoUID],
+ ctUid,
+ models
+ );
+
+ set(data, ['components', compoUID, 'layouts', 'edit'], formattedCompoEditLayout);
+ });
+
+ return data;
+};
+
const formatLayoutWithMetas = (obj, ctUid, models) => {
const formatted = obj.layouts.edit.reduce((acc, current) => {
const row = current.map(attribute => {
@@ -32,8 +79,18 @@ const formatLayoutWithMetas = (obj, ctUid, models) => {
return formatted;
};
-const getDisplayedModels = models =>
- models.filter(model => model.isDisplayed).map(({ uid }) => uid);
+const formatListLayoutWithMetas = obj => {
+ const formatted = obj.layouts.list.reduce((acc, current) => {
+ const fieldSchema = get(obj, ['attributes', current], {});
+ const metadatas = get(obj, ['metadatas', current, 'list'], {});
+
+ acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas });
+
+ return acc;
+ }, []);
+
+ return formatted;
+};
const generateRelationQueryInfos = (obj, fieldName, models) => {
const uid = obj.uid;
@@ -70,65 +127,15 @@ const generateRelationQueryInfosForComponents = (obj, fieldName, ctUid, models)
return queryInfos;
};
-// editRelations is an array of strings...
-const formatEditRelationsLayoutWithMetas = (obj, models) => {
- const formatted = obj.layouts.editRelations.reduce((acc, current) => {
- const fieldSchema = get(obj, ['attributes', current], {});
- const metadatas = get(obj, ['metadatas', current, 'edit'], {});
- const size = 6;
-
- const queryInfos = generateRelationQueryInfos(obj, current, models);
-
- acc.push({
- name: current,
- size,
- fieldSchema,
- metadatas,
- queryInfos,
- });
-
- return acc;
- }, []);
-
- return formatted;
-};
-
-const formatListLayoutWithMetas = obj => {
- const formatted = obj.layouts.list.reduce((acc, current) => {
- const fieldSchema = get(obj, ['attributes', current], {});
- const metadatas = get(obj, ['metadatas', current, 'list'], {});
-
- acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas });
-
- return acc;
- }, []);
-
- return formatted;
-};
-
-const formatLayouts = (initialData, models) => {
- const data = mergeMetasWithSchema(cloneDeep(initialData), models, 'contentType');
- const formattedCTEditLayout = formatLayoutWithMetas(data.contentType, models);
- const ctUid = data.contentType.uid;
- const formattedEditRelationsLayout = formatEditRelationsLayoutWithMetas(data.contentType, models);
- const formattedListLayout = formatListLayoutWithMetas(data.contentType);
-
- set(data, ['contentType', 'layouts', 'edit'], formattedCTEditLayout);
- set(data, ['contentType', 'layouts', 'editRelations'], formattedEditRelationsLayout);
- set(data, ['contentType', 'layouts', 'list'], formattedListLayout);
-
- Object.keys(data.components).forEach(compoUID => {
- const formattedCompoEditLayout = formatLayoutWithMetas(
- data.components[compoUID],
- ctUid,
- models
- );
-
- set(data, ['components', compoUID, 'layouts', 'edit'], formattedCompoEditLayout);
- });
-
- return data;
-};
+const getDisplayedModels = models =>
+ models.filter(model => model.isDisplayed).map(({ uid }) => uid);
export default formatLayouts;
-export { formatEditRelationsLayoutWithMetas, formatLayoutWithMetas };
+export {
+ formatEditRelationsLayoutWithMetas,
+ formatLayoutWithMetas,
+ formatListLayoutWithMetas,
+ generateRelationQueryInfos,
+ generateRelationQueryInfosForComponents,
+ getDisplayedModels,
+};
diff --git a/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js b/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js
index 1484de1116..3315ef5c82 100644
--- a/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js
+++ b/packages/strapi-plugin-content-manager/admin/src/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js
@@ -1,12 +1,70 @@
-import formatLayouts, { formatLayoutWithMetas } from '../formatLayouts';
+import formatLayouts, {
+ formatEditRelationsLayoutWithMetas,
+ formatLayoutWithMetas,
+ formatListLayoutWithMetas,
+ generateRelationQueryInfos,
+ generateRelationQueryInfosForComponents,
+ getDisplayedModels,
+} from '../formatLayouts';
+
+const addressSchema = {
+ uid: 'application::address.address',
+ attributes: {
+ categories: {
+ targetModel: 'application::category.category',
+ },
+ },
+ layouts: {
+ editRelations: ['categories'],
+ },
+ metadatas: {
+ categories: {
+ edit: {
+ mainField: 'name',
+ },
+ },
+ },
+};
+const simpleModels = [
+ {
+ uid: 'application::category.category',
+ isDisplayed: true,
+ },
+];
+
+describe('Content Manager | hooks | useFetchContentTypeLayout | utils ', () => {
+ describe('formatEditRelationsLayoutWithMetas', () => {
+ it('should format editRelations layout correctly', () => {
+ const expectedLayout = [
+ {
+ name: 'categories',
+ size: 6,
+ fieldSchema: {
+ targetModel: 'application::category.category',
+ },
+ metadatas: {
+ mainField: 'name',
+ },
+ queryInfos: {
+ endPoint: '/content-manager/relations/application::address.address/categories',
+ containsKey: 'name_contains',
+ defaultParams: {},
+ shouldDisplayRelationLink: true,
+ },
+ },
+ ];
+
+ expect(formatEditRelationsLayoutWithMetas(addressSchema, simpleModels)).toEqual(
+ expectedLayout
+ );
+ });
+ });
-describe('Content Manager | hooks | useFetchContentTypeLayout | utils | formatLayoutWithMetas', () => {
describe('formatLayouts', () => {
it('should format the content type and components layouts', () => {
const models = [
{
uid: 'compo',
-
attributes: {
full_name: {
type: 'string',
@@ -33,7 +91,6 @@ describe('Content Manager | hooks | useFetchContentTypeLayout | utils | formatLa
type: 'string',
required: true,
},
-
city: {
type: 'string',
maxLength: 100,
@@ -53,7 +110,6 @@ describe('Content Manager | hooks | useFetchContentTypeLayout | utils | formatLa
components: {
compo: {
uid: 'compo',
-
layouts: {
edit: [
[
@@ -157,7 +213,6 @@ describe('Content Manager | hooks | useFetchContentTypeLayout | utils | formatLa
expect(result.contentType).toHaveProperty('attributes');
expect(result.contentType).toHaveProperty('layouts');
expect(result.contentType).toHaveProperty('metadatas');
-
expect(result.contentType.layouts.edit).toEqual([
[
{
@@ -421,4 +476,76 @@ describe('Content Manager | hooks | useFetchContentTypeLayout | utils | formatLa
expect(formatLayoutWithMetas(data)).toEqual(expected);
});
});
+
+ describe('formatListLayoutWithMetas', () => {
+ it('should format the list layout correctly', () => {
+ const data = {
+ layouts: {
+ list: ['test'],
+ },
+ metadatas: {
+ test: {
+ list: { ok: true },
+ },
+ },
+ attributes: {
+ test: { type: 'string' },
+ },
+ };
+ const expected = [
+ {
+ name: 'test',
+ key: '__test_key__',
+ metadatas: { ok: true },
+ fieldSchema: { type: 'string' },
+ },
+ ];
+
+ expect(formatListLayoutWithMetas(data)).toEqual(expected);
+ });
+ });
+
+ describe('generateRelationQueryInfos', () => {
+ it('should return an object with the correct keys', () => {
+ expect(generateRelationQueryInfos(addressSchema, 'categories', simpleModels)).toEqual({
+ endPoint: '/content-manager/relations/application::address.address/categories',
+ containsKey: 'name_contains',
+ defaultParams: {},
+ shouldDisplayRelationLink: true,
+ });
+ });
+ });
+
+ describe('generateRelationQueryInfosForComponents', () => {
+ it('should return an object with the correct keys', () => {
+ expect(
+ generateRelationQueryInfosForComponents(
+ addressSchema,
+ 'categories',
+ 'application::address.address',
+ simpleModels
+ )
+ ).toEqual({
+ endPoint: '/content-manager/relations/application::address.address/categories',
+ containsKey: 'name_contains',
+ defaultParams: {
+ _component: 'application::address.address',
+ },
+ shouldDisplayRelationLink: true,
+ });
+ });
+ });
+
+ describe('getDisplayedModels', () => {
+ it('should return an array containing only the displayable models', () => {
+ const models = [
+ { uid: 'test', isDisplayed: false },
+ { uid: 'testtest', isDisplayed: true },
+ ];
+
+ expect(getDisplayedModels([])).toHaveLength(0);
+ expect(getDisplayedModels(models)).toHaveLength(1);
+ expect(getDisplayedModels(models)[0]).toEqual('testtest');
+ });
+ });
});
diff --git a/packages/strapi-plugin-content-manager/admin/src/utils/formatFiltersFromQuery.js b/packages/strapi-plugin-content-manager/admin/src/utils/formatFiltersFromQuery.js
index ade4770628..12874a714a 100644
--- a/packages/strapi-plugin-content-manager/admin/src/utils/formatFiltersFromQuery.js
+++ b/packages/strapi-plugin-content-manager/admin/src/utils/formatFiltersFromQuery.js
@@ -1,30 +1,37 @@
-const findAppliedFilter = str => {
- let filter = '=';
- let name = str;
+// List of all the possible filters
+const VALID_REST_OPERATORS = [
+ 'eq',
+ 'ne',
+ 'in',
+ 'nin',
+ 'contains',
+ 'ncontains',
+ 'containss',
+ 'ncontainss',
+ 'lt',
+ 'lte',
+ 'gt',
+ 'gte',
+ 'null',
+];
- const filters = [
- '_ne',
- '_lt',
- '_lte',
- '_gt',
- '_gte',
- '_contains',
- '_containss',
- '_ncontains',
- '_in',
- '_nin',
- ];
+// from strapi-utims/convert-rest-query-params
+const findAppliedFilter = whereClause => {
+ const separatorIndex = whereClause.lastIndexOf('_');
- filters.forEach(filterName => {
- const split = str.split(filterName);
+ if (separatorIndex === -1) {
+ return { operator: '=', field: whereClause };
+ }
- if (split[1] === '') {
- filter = filterName;
- name = split[0];
- }
- });
+ const fieldName = whereClause.substring(0, separatorIndex);
+ const operator = whereClause.slice(separatorIndex + 1);
- return { filter, name };
+ // the field as underscores
+ if (!VALID_REST_OPERATORS.includes(operator)) {
+ return { operator: '=', field: whereClause };
+ }
+
+ return { operator: `_${operator}`, field: fieldName };
};
const formatFiltersFromQuery = ({ _where }) => {
@@ -34,11 +41,11 @@ const formatFiltersFromQuery = ({ _where }) => {
return _where.map(obj => {
const [key] = Object.keys(obj);
- const { filter, name } = findAppliedFilter(key);
+ const { field, operator } = findAppliedFilter(key);
const value = obj[key];
- return { name, filter, value };
+ return { name: field, filter: operator, value };
});
};
diff --git a/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatFilterFromQuery.test.js b/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatFilterFromQuery.test.js
new file mode 100644
index 0000000000..5203a67b79
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatFilterFromQuery.test.js
@@ -0,0 +1,45 @@
+import formatFiltersFromQuery, { findAppliedFilter } from '../formatFiltersFromQuery';
+
+describe('CONTENT MANAGER | utils', () => {
+ describe('findAppliedFilter', () => {
+ it('should return the correct filter', () => {
+ expect(findAppliedFilter('city')).toEqual({ operator: '=', field: 'city' });
+ expect(findAppliedFilter('city_nee')).toEqual({ operator: '=', field: 'city_nee' });
+ expect(findAppliedFilter('city_ne')).toEqual({ operator: '_ne', field: 'city' });
+ expect(findAppliedFilter('city_lt')).toEqual({ operator: '_lt', field: 'city' });
+ expect(findAppliedFilter('city_lte')).toEqual({ operator: '_lte', field: 'city' });
+ expect(findAppliedFilter('city_gt')).toEqual({ operator: '_gt', field: 'city' });
+ expect(findAppliedFilter('city_gte')).toEqual({ operator: '_gte', field: 'city' });
+ });
+ });
+
+ describe('formatFiltersFromQuery', () => {
+ it('should return an empty array if there is no where clause', () => {
+ expect(formatFiltersFromQuery({})).toHaveLength(0);
+ });
+
+ it('should return array of filter', () => {
+ const query = {
+ _where: [
+ {
+ city_ne_ne: 'paris',
+ },
+ {
+ city_ne: 'paris',
+ },
+ {
+ city: 'paris',
+ },
+ ],
+ };
+
+ const expected = [
+ { name: 'city_ne', filter: '_ne', value: 'paris' },
+ { name: 'city', filter: '_ne', value: 'paris' },
+ { name: 'city', filter: '=', value: 'paris' },
+ ];
+
+ expect(formatFiltersFromQuery(query)).toEqual(expected);
+ });
+ });
+});
diff --git a/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatLayoutToApi.test.js b/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatLayoutToApi.test.js
new file mode 100644
index 0000000000..98c96d0ce2
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/utils/tests/formatLayoutToApi.test.js
@@ -0,0 +1,23 @@
+import formatLayoutToApi from '../formatLayoutToApi';
+
+describe('CONTENT MANAGER | utils | formatLayoutToApi', () => {
+ it('should format the list layout correctly if it is an array of objects', () => {
+ const layouts = {
+ list: [{ name: 'test', size: 6 }],
+ edit: [],
+ editRelations: [],
+ };
+
+ expect(formatLayoutToApi({ layouts }).layouts.list).toEqual(['test']);
+ });
+
+ it('should format the list layout correctly if it is an array of strings', () => {
+ const layouts = {
+ list: ['test'],
+ edit: [],
+ editRelations: [],
+ };
+
+ expect(formatLayoutToApi({ layouts }).layouts.list).toEqual(['test']);
+ });
+});