mirror of
https://github.com/strapi/strapi.git
synced 2025-08-12 18:53:23 +00:00
Single types list in CTB
Signed-off-by: Hicham EL ABBASSI <hichamelabbassi@MacBook-Pro-de-Hicham.local> Signed-off-by: HichamELBSI <elabbassih@gmail.com>
This commit is contained in:
parent
90a60879c5
commit
73db8d428b
@ -1,6 +1,6 @@
|
||||
import React, { memo, useEffect, useReducer, useState, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { camelCase, get, groupBy, set, size, sortBy } from 'lodash';
|
||||
import { get, groupBy, set, size } from 'lodash';
|
||||
import {
|
||||
request,
|
||||
LoadingIndicatorPage,
|
||||
@ -32,6 +32,7 @@ import {
|
||||
getComponentsToPost,
|
||||
formatMainDataType,
|
||||
getCreatedAndModifiedComponents,
|
||||
sortContentType,
|
||||
} from './utils/cleanData';
|
||||
|
||||
const DataManagerProvider = ({ allIcons, children }) => {
|
||||
@ -86,7 +87,6 @@ const DataManagerProvider = ({ allIcons, children }) => {
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const components = createDataObject(componentsArray);
|
||||
const contentTypes = createDataObject(contentTypesArray);
|
||||
const orderedComponents = orderAllDataAttributesWithImmutable({
|
||||
@ -373,18 +373,6 @@ const DataManagerProvider = ({ allIcons, children }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const sortedContentTypesList = sortBy(
|
||||
Object.keys(contentTypes)
|
||||
.map(uid => ({
|
||||
name: uid,
|
||||
title: contentTypes[uid].schema.name,
|
||||
uid,
|
||||
to: `/plugins/${pluginId}/content-types/${uid}`,
|
||||
}))
|
||||
.filter(obj => obj !== null),
|
||||
obj => camelCase(obj.title)
|
||||
);
|
||||
|
||||
const shouldRedirect = () => {
|
||||
const dataSet = isInContentTypeView ? contentTypes : components;
|
||||
|
||||
@ -520,7 +508,7 @@ const DataManagerProvider = ({ allIcons, children }) => {
|
||||
removeAttribute,
|
||||
removeComponentFromDynamicZone,
|
||||
setModifiedData,
|
||||
sortedContentTypesList,
|
||||
sortedContentTypesList: sortContentType(contentTypes),
|
||||
submitData,
|
||||
toggleModalCancel,
|
||||
updateSchema,
|
||||
|
@ -385,6 +385,14 @@ describe('CTB | containers | DataManagerProvider | reducer | basics actions ', (
|
||||
},
|
||||
},
|
||||
};
|
||||
const singleTypes = {
|
||||
'application::aboutpage.aboutpage': {
|
||||
uid: 'application::aboutpage.aboutpage',
|
||||
schema: {
|
||||
attributes: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = initialState
|
||||
.set('components', fromJS(components))
|
||||
.set('contentTypes', fromJS(contentTypes))
|
||||
@ -397,6 +405,7 @@ describe('CTB | containers | DataManagerProvider | reducer | basics actions ', (
|
||||
type: 'GET_DATA_SUCCEEDED',
|
||||
components,
|
||||
contentTypes,
|
||||
singleTypes,
|
||||
})
|
||||
).toEqual(expected);
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { get, has, isEqual, omit } from 'lodash';
|
||||
import { get, has, isEqual, omit, sortBy, camelCase } from 'lodash';
|
||||
|
||||
import pluginId from '../../../pluginId';
|
||||
import makeUnique from '../../../utils/makeUnique';
|
||||
|
||||
const getCreatedAndModifiedComponents = (allComponents, initialComponents) => {
|
||||
@ -157,9 +159,24 @@ const getComponentsToPost = (
|
||||
return formattedComponents;
|
||||
};
|
||||
|
||||
const sortContentType = types =>
|
||||
sortBy(
|
||||
Object.keys(types)
|
||||
.map(uid => ({
|
||||
name: uid,
|
||||
title: types[uid].schema.name,
|
||||
uid,
|
||||
to: `/plugins/${pluginId}/content-types/${uid}`,
|
||||
kind: types[uid].schema.kind,
|
||||
}))
|
||||
.filter(obj => obj !== null),
|
||||
obj => camelCase(obj.title)
|
||||
);
|
||||
|
||||
export {
|
||||
formatComponent,
|
||||
getComponentsToPost,
|
||||
getCreatedAndModifiedComponents,
|
||||
formatMainDataType,
|
||||
sortContentType,
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
formatMainDataType,
|
||||
getComponentsToPost,
|
||||
getCreatedAndModifiedComponents,
|
||||
sortContentType,
|
||||
} from '../cleanData';
|
||||
import rawData from './rawData';
|
||||
import expectedData from './expectedFormattedData';
|
||||
@ -207,4 +208,19 @@ describe('CleanData utils', () => {
|
||||
).toEqual(componentsToFormat.sort());
|
||||
});
|
||||
});
|
||||
|
||||
describe('sortContentType', () => {
|
||||
it('should return sorted collection types array', () => {
|
||||
const { sortedContentTypes } = expectedData;
|
||||
const {
|
||||
rawData: { contentTypesToSort },
|
||||
} = rawData;
|
||||
|
||||
const actual = sortContentType(contentTypesToSort);
|
||||
expect(actual.sort()).toEqual(sortedContentTypes.sort());
|
||||
});
|
||||
it('should return an empty array if no content types', () => {
|
||||
expect(sortContentType({})).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -96,6 +96,39 @@ const expectedData = {
|
||||
'default.nested-compo',
|
||||
'blog.quote',
|
||||
],
|
||||
sortedContentTypes: [
|
||||
{
|
||||
uid: 'plugins::myplugins.atest',
|
||||
name: 'plugins::myplugins.atest',
|
||||
title: 'plugins::myplugins.atest',
|
||||
to:
|
||||
'/plugins/content-type-builder/content-types/plugins::myplugins.atest',
|
||||
kind: 'collectionType',
|
||||
},
|
||||
{
|
||||
uid: 'plugins::myplugins.btest',
|
||||
name: 'plugins::myplugins.btest',
|
||||
title: 'plugins::myplugins.btest',
|
||||
to:
|
||||
'/plugins/content-type-builder/content-types/plugins::myplugins.btest',
|
||||
kind: 'collectionType',
|
||||
},
|
||||
{
|
||||
uid: 'plugins::myplugins.ctest',
|
||||
name: 'plugins::myplugins.ctest',
|
||||
title: 'plugins::myplugins.ctest',
|
||||
to:
|
||||
'/plugins/content-type-builder/content-types/plugins::myplugins.ctest',
|
||||
kind: 'collectionType',
|
||||
},
|
||||
{
|
||||
uid: 'plugins::myplugins.test',
|
||||
name: 'plugins::myplugins.test',
|
||||
title: 'plugins::myplugins.test',
|
||||
to: '/plugins/content-type-builder/content-types/plugins::myplugins.test',
|
||||
kind: 'singleType',
|
||||
},
|
||||
],
|
||||
|
||||
components: [
|
||||
{
|
||||
|
@ -147,6 +147,24 @@ const data = {
|
||||
},
|
||||
},
|
||||
},
|
||||
contentTypesToSort: {
|
||||
'plugins::myplugins.test': {
|
||||
uid: 'plugins::myplugins.test',
|
||||
schema: { name: 'plugins::myplugins.test', kind: 'singleType' },
|
||||
},
|
||||
'plugins::myplugins.btest': {
|
||||
uid: 'plugins::myplugins.btest',
|
||||
schema: { name: 'plugins::myplugins.btest', kind: 'collectionType' },
|
||||
},
|
||||
'plugins::myplugins.atest': {
|
||||
uid: 'plugins::myplugins.atest',
|
||||
schema: { name: 'plugins::myplugins.atest', kind: 'collectionType' },
|
||||
},
|
||||
'plugins::myplugins.ctest': {
|
||||
uid: 'plugins::myplugins.ctest',
|
||||
schema: { name: 'plugins::myplugins.ctest', kind: 'collectionType' },
|
||||
},
|
||||
},
|
||||
// TODO add test for component
|
||||
// componentToCreate: {
|
||||
|
||||
|
@ -86,6 +86,7 @@ const FormModal = () => {
|
||||
const dynamicZoneTarget = query.get('dynamicZoneTarget');
|
||||
const forTarget = query.get('forTarget');
|
||||
const modalType = query.get('modalType');
|
||||
const contentTypeKind = query.get('kind');
|
||||
const targetUid = query.get('targetUid');
|
||||
const settingType = query.get('settingType');
|
||||
const headerId = query.get('headerId');
|
||||
@ -157,6 +158,7 @@ const FormModal = () => {
|
||||
header_info_name_5,
|
||||
header_info_category_5,
|
||||
headerId,
|
||||
contentTypeKind,
|
||||
});
|
||||
|
||||
// Reset all the modification when opening the edit category modal
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { sortBy } from 'lodash';
|
||||
import { sortBy, camelCase, upperFirst } from 'lodash';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { LeftMenuList, useGlobalContext } from 'strapi-helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
@ -32,7 +32,6 @@ function LeftMenu({ wait }) {
|
||||
} = useDataManager();
|
||||
const { emitEvent, formatMessage } = useGlobalContext();
|
||||
const { push } = useHistory();
|
||||
|
||||
const componentsData = sortBy(
|
||||
Object.keys(componentsGroupedByCategory).map(category => ({
|
||||
name: category,
|
||||
@ -86,18 +85,19 @@ function LeftMenu({ wait }) {
|
||||
);
|
||||
};
|
||||
|
||||
const handleClickOpenModal = async type => {
|
||||
const handleClickOpenModal = async (type, kind = '') => {
|
||||
if (canOpenModalCreateCTorComponent()) {
|
||||
const eventName =
|
||||
type === 'contentType'
|
||||
? 'willCreateContentType'
|
||||
: 'willCreateComponent';
|
||||
|
||||
emitEvent(eventName);
|
||||
emitEvent(
|
||||
`willCreate${upperFirst(
|
||||
camelCase(kind === 'singleType' ? kind : type)
|
||||
)}`
|
||||
);
|
||||
|
||||
await wait();
|
||||
push({
|
||||
search: `modalType=${type}&actionType=create&settingType=base&forTarget=${type}&headerId=${getTrad(
|
||||
search: `modalType=${type}${
|
||||
kind ? `&kind=${kind}` : ''
|
||||
}&actionType=create&settingType=base&forTarget=${type}&headerId=${getTrad(
|
||||
`modalForm.${type}.header-create`
|
||||
)}&header_icon_name_1=${type}&header_icon_isCustom_1=false&header_label_1=null`,
|
||||
});
|
||||
@ -105,7 +105,6 @@ function LeftMenu({ wait }) {
|
||||
displayNotificationCTNotSaved();
|
||||
}
|
||||
};
|
||||
|
||||
const data = [
|
||||
{
|
||||
name: 'models',
|
||||
@ -119,12 +118,35 @@ function LeftMenu({ wait }) {
|
||||
componentProps: {
|
||||
id: `${pluginId}.button.model.create`,
|
||||
onClick: () => {
|
||||
handleClickOpenModal('contentType');
|
||||
handleClickOpenModal('contentType', 'collectionType');
|
||||
},
|
||||
},
|
||||
}
|
||||
: null,
|
||||
links: sortedContentTypesList,
|
||||
links: sortedContentTypesList.filter(
|
||||
contentType => contentType.kind === 'collectionType'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'singleTypes',
|
||||
title: {
|
||||
id: `${pluginId}.menu.section.single-types.name.`,
|
||||
},
|
||||
searchable: true,
|
||||
customLink: isInDevelopmentMode
|
||||
? {
|
||||
Component: CustomLink,
|
||||
componentProps: {
|
||||
id: `${pluginId}.button.single-types.create`,
|
||||
onClick: () => {
|
||||
handleClickOpenModal('contentType', 'singleType');
|
||||
},
|
||||
},
|
||||
}
|
||||
: null,
|
||||
links: sortedContentTypesList.filter(
|
||||
singleType => singleType.kind === 'singleType'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'components',
|
||||
|
@ -34,6 +34,7 @@
|
||||
"button.component.add": "Add a component",
|
||||
"button.component.create": "Create new component",
|
||||
"button.model.create": "Create new collection-type",
|
||||
"button.single-types.create": "Create new single-type",
|
||||
"components.componentSelect.no-component-available": "You have already added all your components",
|
||||
"components.componentSelect.no-component-available.with-search": "There is no component matching your search",
|
||||
"components.componentSelect.value-component": "{number} component selected (type to search for a component)",
|
||||
@ -111,6 +112,8 @@
|
||||
"menu.section.components.name.singular": "Component",
|
||||
"menu.section.models.name.plural": "Collection Types",
|
||||
"menu.section.models.name.singular": "Collection Type",
|
||||
"menu.section.single-types.name.plural": "Single Types",
|
||||
"menu.section.single-types.name.singular": "Single Type",
|
||||
"modalForm.attribute.form.base.name": "Name",
|
||||
"modalForm.attribute.form.base.name.description": "No space is allowed for the name of the attribute",
|
||||
"modalForm.attribute.text.type-selection": "Type",
|
||||
@ -120,6 +123,7 @@
|
||||
"modalForm.components.create-component.category.label": "Select a category or enter a name to create a new one",
|
||||
"modalForm.components.icon.label": "Icon",
|
||||
"modalForm.contentType.header-create": "Create a collection type",
|
||||
"modalForm.singleType.header-create": "Create a single type",
|
||||
"modalForm.editCategory.base.name.description": "No space is allowed for the name of the category",
|
||||
"modalForm.header-edit": "Edit {name}",
|
||||
"modalForm.header.categories": "Categories",
|
||||
|
@ -10,8 +10,8 @@
|
||||
"attribute.richtext": "Texte enrichi",
|
||||
"attribute.text": "Texte",
|
||||
"button.attributes.add.another": "Ajouter un autre champ",
|
||||
"button.component.create": "Créer un Composant",
|
||||
"button.model.create": "Créer un Type de Collection",
|
||||
"button.component.create": "Créer un composant",
|
||||
"button.model.create": "Créer un type de collection",
|
||||
"form.attribute.item.customColumnName": "Nom de colonne personalisée",
|
||||
"form.attribute.item.customColumnName.description": "Pratique pour renommer la colonne de la db dans un format plus comprehensible pour les responses de l'API",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nom du Champ",
|
||||
@ -44,6 +44,10 @@
|
||||
"menu.section.components.name.singular": "Composant",
|
||||
"menu.section.models.name.plural": "Modèles",
|
||||
"menu.section.models.name.singular": "Modèle",
|
||||
"menu.section.single-types.name.plural": "Single Types",
|
||||
"menu.section.single-types.name.singular": "Single Type",
|
||||
"modalForm.singleType.header-create": "Créer un single type",
|
||||
"button.single-types.create": "Créer un single type",
|
||||
"modelPage.attribute.relationWith": "Relation avec",
|
||||
"modelPage.contentHeader.emptyDescription.description": "Il n'y a pas de description",
|
||||
"plugin.description.long": "Modélisez la structure de données de votre API. Créer des nouveaux champs et relations en un instant. Les fichiers se créent et se mettent à jour automatiquement.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user