Add components select

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-10-13 17:34:20 +02:00
parent 97950e25b1
commit 25065ba0c8
8 changed files with 91 additions and 124 deletions

View File

@ -1,5 +1,3 @@
export const ADD_COMPONENTS_TO_DYNAMIC_ZONE =
'ContentTypeBuilder/FormModal/ADD_COMPONENTS_TO_DYNAMIC_ZONE';
export const ON_CHANGE = 'ContentTypeBuilder/FormModal/ON_CHANGE';
export const ON_CHANGE_RELATION_TARGET = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TARGET';
export const ON_CHANGE_RELATION_TYPE = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TYPE';

View File

@ -35,7 +35,7 @@ const form = {
},
{
name: 'components',
type: 'componentSelect',
type: 'select-components',
intlLabel: {
id: getTrad('modalForm.attributes.select-components'),
defaultMessage: 'Select the components',

View File

@ -37,6 +37,7 @@ import ComponentIconPicker from '../ComponentIconPicker';
import Relation from '../Relation';
import SelectCategory from '../SelectCategory';
import SelectComponent from '../SelectComponent';
import SelectComponents from '../SelectComponents';
// import SelectCategory from '../WrapperSelect';
// import WrapperSelect from '../WrapperSelect';
import findAttribute from '../../utils/findAttribute';
@ -59,7 +60,6 @@ import {
SET_DATA_TO_EDIT,
SET_DYNAMIC_ZONE_DATA_SCHEMA,
SET_ATTRIBUTE_DATA_SCHEMA,
// ADD_COMPONENTS_TO_DYNAMIC_ZONE,
SET_ERRORS,
ON_CHANGE,
RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ,
@ -554,17 +554,6 @@ const FormModal = () => {
}, '');
};
// const handleClickAddComponentsToDynamicZone = ({
// target: { name, components, shouldAddComponents },
// }) => {
// dispatch({
// type: ADD_COMPONENTS_TO_DYNAMIC_ZONE,
// name,
// components,
// shouldAddComponents,
// });
// };
const handleChange = useCallback(
({ target: { name, value, type, ...rest } }) => {
const namesThatCanResetToNullValue = [
@ -1099,11 +1088,13 @@ const FormModal = () => {
relation: Relation,
'select-category': SelectCategory,
'select-component': SelectComponent,
'select-components': SelectComponents,
'select-default-boolean': BooleanDefaultValueSelect,
'toggle-draft-publish': DraftAndPublishToggle,
...inputsFromPlugins,
},
componentToCreate,
dynamicZoneTarget: state.dynamicZoneTarget,
formErrors,
isAddingAComponentToAnotherComponent,
isCreatingComponentWhileAddingAField,

View File

@ -3,7 +3,6 @@ import pluralize from 'pluralize';
import set from 'lodash/set';
import snakeCase from 'lodash/snakeCase';
import getRelationType from '../../utils/getRelationType';
import makeUnique from '../../utils/makeUnique';
import { createComponentUid } from './utils/createUid';
import { shouldPluralizeName, shouldPluralizeTargetAttribute } from './utils/relations';
import * as actions from './constants';
@ -20,22 +19,6 @@ const reducer = (state = initialState, action) =>
// eslint-disable-next-line consistent-return
produce(state, draftState => {
switch (action.type) {
case actions.ADD_COMPONENTS_TO_DYNAMIC_ZONE: {
const { components, shouldAddComponents } = action;
let currentList = [];
if (shouldAddComponents) {
currentList = [...state.modifiedData.components, ...components];
} else {
currentList = state.modifiedData.components.filter(comp => {
return components.indexOf(comp) === -1;
});
}
draftState.modifiedData.components = makeUnique(currentList);
break;
}
case actions.ON_CHANGE: {
const { keys, value } = action;
const obj = state.modifiedData;

View File

@ -2,66 +2,6 @@ import reducer, { initialState } from '../reducer';
import * as actions from '../constants';
describe('CTB | components | FormModal | reducer | actions', () => {
describe('ADD_COMPONENTS_TO_DYNAMIC_ZONE', () => {
it('Should add the components correctly', () => {
const action = {
type: actions.ADD_COMPONENTS_TO_DYNAMIC_ZONE,
components: ['default.test', 'default.test2', 'default.test3'],
shouldAddComponents: true,
name: 'components',
};
const state = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test'],
},
};
const expected = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test', 'default.test2', 'default.test3'],
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should remove the components correctly', () => {
const action = {
type: actions.ADD_COMPONENTS_TO_DYNAMIC_ZONE,
components: ['default.test2', 'default.test3'],
shouldAddComponents: false,
name: 'components',
};
const state = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test', 'default.test2', 'default.test3'],
},
};
const expected = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test'],
},
};
expect(reducer(state, action)).toEqual(expected);
});
});
describe(actions.ON_CHANGE, () => {
it('Should update the modifiedData object correctly', () => {
const action = {

View File

@ -1,31 +0,0 @@
/**
*
* Tests for SelectComponent
*
*/
import React from 'react';
import { render } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import { IntlProvider } from 'react-intl';
import SelectComponent from '../index';
const messages = {
'content-type-builder.component.name': 'Select Component',
};
describe('<SelectComponent />', () => {
it('renders and matches the snapshot', () => {
const {
container: { firstChild },
} = render(
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={messages} defaultLocale="en">
<SelectComponent />
</IntlProvider>
</ThemeProvider>
);
expect(firstChild).toMatchInlineSnapshot();
});
});

View File

@ -0,0 +1,85 @@
/**
*
* SelectComponents
*
*/
import React from 'react';
import PropTypes from 'prop-types';
import { MultiSelectNested } from '@strapi/parts/Select';
import { useIntl } from 'react-intl';
import useDataManager from '../../hooks/useDataManager';
import findAttribute from '../../utils/findAttribute';
import { getTrad } from '../../utils';
const SelectComponents = ({ dynamicZoneTarget, intlLabel, name, onChange, value }) => {
const { formatMessage } = useIntl();
const { componentsGroupedByCategory, modifiedData } = useDataManager();
const dzSchema =
findAttribute(modifiedData.contentType.schema.attributes, dynamicZoneTarget) || {};
const alreadyUsedComponents = dzSchema.components || [];
const filteredComponentsGroupedByCategory = Object.keys(componentsGroupedByCategory).reduce(
(acc, current) => {
const filteredComponents = componentsGroupedByCategory[current].filter(({ uid }) => {
return !alreadyUsedComponents.includes(uid);
});
if (filteredComponents.length > 0) {
acc[current] = filteredComponents;
}
return acc;
},
{}
);
const options = Object.entries(filteredComponentsGroupedByCategory).reduce((acc, current) => {
const [categoryName, components] = current;
const section = {
label: categoryName,
children: components.map(({ uid, schema: { name } }) => {
return { label: name, value: uid };
}),
};
acc.push(section);
return acc;
}, []);
const displayedValue = formatMessage(
{
id: getTrad('components.SelectComponents.displayed-value'),
defaultMessage:
'{number, plural, =0 {# components} one {# component} other {# components}} selected',
},
{ number: value.length }
);
return (
<MultiSelectNested
id="select1"
label={formatMessage(intlLabel)}
customizeContent={() => displayedValue}
name={name}
onChange={values => {
onChange({ target: { name, value: values, type: 'select-components' } });
}}
options={options}
value={value || []}
/>
);
};
SelectComponents.propTypes = {
intlLabel: PropTypes.shape({
id: PropTypes.string.isRequired,
defaultMessage: PropTypes.string.isRequired,
values: PropTypes.object,
}).isRequired,
dynamicZoneTarget: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
value: PropTypes.array.isRequired,
};
export default SelectComponents;

View File

@ -190,5 +190,6 @@
"table.button.no-fields": "Add new field",
"table.headers.name": "Name",
"table.headers.type": "Type",
"ComponentIconPicker.search.placeholder": "Search for an icon"
"ComponentIconPicker.search.placeholder": "Search for an icon",
"components.SelectComponents.displayed-value": "{number, plural, =0 {# components} one {# component} other {# components}} selected"
}