mirror of
https://github.com/strapi/strapi.git
synced 2025-09-20 05:52:08 +00:00
Migrate AllowedTypesSelect
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
548cc9a88e
commit
7148972f00
@ -1,115 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { CheckboxWrapper, Label } from '@buffetjs/styles';
|
|
||||||
import getTrad from '../../utils/getTrad';
|
|
||||||
import SelectCheckbox from '../SelectCheckbox';
|
|
||||||
import SubUl from '../SelectMenuSubUl';
|
|
||||||
import UpperFirst from '../UpperFirst';
|
|
||||||
import Ul from '../SelectMenuUl';
|
|
||||||
import Text from './Text';
|
|
||||||
|
|
||||||
const MenuList = ({ selectProps: { changeMediaAllowedTypes, value }, ...rest }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
const Component = components.MenuList;
|
|
||||||
const areAllAllowedTypesSelected = value.value && value.value.length === 3;
|
|
||||||
const someChecked = value.value && !areAllAllowedTypesSelected && value.value.length > 0;
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
name: 'images',
|
|
||||||
infos: '(JPEG, PNG, GIF, SVG, TIFF, ICO, DVU)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'videos',
|
|
||||||
infos: '(MPEG, MP4, Quicktime, WMV, AVI, FLV)',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'files',
|
|
||||||
infos: '(CSV, ZIP, MP3, PDF, Excel, JSON, ...)',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Component {...rest}>
|
|
||||||
<Ul>
|
|
||||||
<li className="li-multi-menu">
|
|
||||||
<div style={{ marginTop: 3 }}>
|
|
||||||
<CheckboxWrapper>
|
|
||||||
<Label
|
|
||||||
htmlFor="overrideReactSelectBehavior"
|
|
||||||
onClick={() => {
|
|
||||||
changeMediaAllowedTypes({
|
|
||||||
target: { name: 'all', value: !areAllAllowedTypesSelected },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectCheckbox
|
|
||||||
id="checkAll"
|
|
||||||
checked={areAllAllowedTypesSelected}
|
|
||||||
someChecked={someChecked}
|
|
||||||
name="all"
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
<UpperFirst content="All" />
|
|
||||||
</Label>
|
|
||||||
</CheckboxWrapper>
|
|
||||||
</div>
|
|
||||||
<SubUl tad="ul" isOpen>
|
|
||||||
{options.map(({ name, infos }) => {
|
|
||||||
const isChecked = value.value && value.value.includes(name);
|
|
||||||
const target = { name, value: !isChecked };
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li key={name}>
|
|
||||||
<CheckboxWrapper>
|
|
||||||
<Label
|
|
||||||
htmlFor={name}
|
|
||||||
onClick={() => {
|
|
||||||
changeMediaAllowedTypes({ target });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectCheckbox
|
|
||||||
id="check"
|
|
||||||
name={name}
|
|
||||||
// Remove the handler
|
|
||||||
onChange={() => {}}
|
|
||||||
checked={isChecked}
|
|
||||||
/>
|
|
||||||
<Text>
|
|
||||||
<UpperFirst
|
|
||||||
content={formatMessage({
|
|
||||||
id: getTrad(`form.attribute.media.allowed-types.option-${name}`),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
<Text fontSize="sm" color="#B3B5B9" textTransform="italic">
|
|
||||||
{infos}
|
|
||||||
</Text>
|
|
||||||
</Label>
|
|
||||||
</CheckboxWrapper>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</SubUl>
|
|
||||||
</li>
|
|
||||||
</Ul>
|
|
||||||
</Component>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
MenuList.defaultProps = {
|
|
||||||
selectProps: {
|
|
||||||
value: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
MenuList.propTypes = {
|
|
||||||
selectProps: PropTypes.shape({
|
|
||||||
changeMediaAllowedTypes: PropTypes.func.isRequired,
|
|
||||||
value: PropTypes.object,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MenuList;
|
|
@ -1,26 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const Text = styled.p`
|
|
||||||
display: contents;
|
|
||||||
color: ${({ theme, color }) => theme.main.colors[color] || color};
|
|
||||||
font-size: ${({ theme, fontSize }) => theme.main.sizes.fonts[fontSize]};
|
|
||||||
font-weight: ${({ theme, fontWeight }) => theme.main.fontWeights[fontWeight]};
|
|
||||||
text-transform: ${({ textTransform }) => textTransform};
|
|
||||||
`;
|
|
||||||
|
|
||||||
Text.defaultProps = {
|
|
||||||
color: 'black',
|
|
||||||
fontSize: 'md',
|
|
||||||
fontWeight: 'regular',
|
|
||||||
textTransform: 'none',
|
|
||||||
};
|
|
||||||
|
|
||||||
Text.propTypes = {
|
|
||||||
color: PropTypes.string,
|
|
||||||
fontSize: PropTypes.string,
|
|
||||||
fontWeight: PropTypes.string,
|
|
||||||
textTransform: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Text;
|
|
@ -1,18 +1,23 @@
|
|||||||
import React, { useRef } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Select from 'react-select';
|
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import { MultiSelectNested } from '@strapi/parts/Select';
|
||||||
import upperFirst from 'lodash/upperFirst';
|
import upperFirst from 'lodash/upperFirst';
|
||||||
import MenuList from './MenuList';
|
|
||||||
import getTrad from '../../utils/getTrad';
|
import getTrad from '../../utils/getTrad';
|
||||||
|
|
||||||
const AllowedTypesSelect = ({ name, changeMediaAllowedTypes, styles, value }) => {
|
const options = [
|
||||||
|
{
|
||||||
|
label: 'All',
|
||||||
|
children: [
|
||||||
|
{ label: 'images (JPEG, PNG, GIF, SVG, TIFF, ICO, DVU)', value: 'images' },
|
||||||
|
{ label: 'videos (MPEG, MP4, Quicktime, WMV, AVI, FLV)', value: 'videos' },
|
||||||
|
{ label: 'files (CSV, ZIP, MP3, PDF, Excel, JSON, ...)', value: 'files' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const AllowedTypesSelect = ({ intlLabel, name, onChange, value }) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
// Create a ref in order to access the StateManager
|
|
||||||
// So we can close the menu after clicking on a menu item
|
|
||||||
// This allows us to get rid of the menuIsOpen state management
|
|
||||||
// So we let the custom components taking care of it
|
|
||||||
const ref = useRef();
|
|
||||||
|
|
||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
|
|
||||||
@ -26,17 +31,24 @@ const AllowedTypesSelect = ({ name, changeMediaAllowedTypes, styles, value }) =>
|
|||||||
|
|
||||||
/* eslint-enable indent */
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
const label = intlLabel.id
|
||||||
|
? formatMessage({ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage })
|
||||||
|
: name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<MultiSelectNested
|
||||||
components={{ MenuList }}
|
id="select1"
|
||||||
isClearable={false}
|
label={label}
|
||||||
isSearchable={false}
|
customizeContent={() => displayedValue}
|
||||||
name={name}
|
onChange={values => {
|
||||||
changeMediaAllowedTypes={changeMediaAllowedTypes}
|
if (values.length > 0) {
|
||||||
ref={ref}
|
onChange({ target: { name, value: values, type: 'allowed-types-select' } });
|
||||||
refState={ref}
|
} else {
|
||||||
styles={styles}
|
onChange({ target: { name, value: null, type: 'allowed-types-select' } });
|
||||||
value={{ label: displayedValue, value: value || '' }}
|
}
|
||||||
|
}}
|
||||||
|
options={options}
|
||||||
|
value={value || []}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -46,9 +58,13 @@ AllowedTypesSelect.defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AllowedTypesSelect.propTypes = {
|
AllowedTypesSelect.propTypes = {
|
||||||
changeMediaAllowedTypes: PropTypes.func.isRequired,
|
intlLabel: PropTypes.shape({
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
defaultMessage: PropTypes.string.isRequired,
|
||||||
|
values: PropTypes.object,
|
||||||
|
}).isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
styles: PropTypes.object.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -239,7 +239,8 @@ const advancedForm = {
|
|||||||
defaultMessage: 'Select allowed types of media',
|
defaultMessage: 'Select allowed types of media',
|
||||||
},
|
},
|
||||||
name: 'allowedTypes',
|
name: 'allowedTypes',
|
||||||
type: 'allowedTypesSelect',
|
type: 'allowed-types-select',
|
||||||
|
size: 7,
|
||||||
value: '',
|
value: '',
|
||||||
validations: {},
|
validations: {},
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
export const ADD_COMPONENTS_TO_DYNAMIC_ZONE =
|
export const ADD_COMPONENTS_TO_DYNAMIC_ZONE =
|
||||||
'ContentTypeBuilder/FormModal/ADD_COMPONENTS_TO_DYNAMIC_ZONE';
|
'ContentTypeBuilder/FormModal/ADD_COMPONENTS_TO_DYNAMIC_ZONE';
|
||||||
export const ON_CHANGE = 'ContentTypeBuilder/FormModal/ON_CHANGE';
|
export const ON_CHANGE = 'ContentTypeBuilder/FormModal/ON_CHANGE';
|
||||||
export const ON_CHANGE_ALLOWED_TYPE = 'ContentTypeBuilder/FormModal/ON_CHANGE_ALLOWED_TYPE';
|
|
||||||
export const ON_CHANGE_RELATION_TARGET = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TARGET';
|
export const ON_CHANGE_RELATION_TARGET = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TARGET';
|
||||||
export const ON_CHANGE_RELATION_TYPE = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TYPE';
|
export const ON_CHANGE_RELATION_TYPE = 'ContentTypeBuilder/FormModal/ON_CHANGE_RELATION_TYPE';
|
||||||
export const RESET_PROPS = 'ContentTypeBuilder/FormModal/RESET_PROPS';
|
export const RESET_PROPS = 'ContentTypeBuilder/FormModal/RESET_PROPS';
|
||||||
|
@ -25,6 +25,7 @@ import { Stack } from '@strapi/parts/Stack';
|
|||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import useDataManager from '../../hooks/useDataManager';
|
import useDataManager from '../../hooks/useDataManager';
|
||||||
// New compos
|
// New compos
|
||||||
|
import AllowedTypesSelect from '../AllowedTypesSelect';
|
||||||
import AttributeOptions from '../AttributeOptions';
|
import AttributeOptions from '../AttributeOptions';
|
||||||
import DraftAndPublishToggle from '../DraftAndPublishToggle';
|
import DraftAndPublishToggle from '../DraftAndPublishToggle';
|
||||||
import FormModalHeader from '../FormModalHeader';
|
import FormModalHeader from '../FormModalHeader';
|
||||||
@ -57,7 +58,6 @@ import {
|
|||||||
SET_DYNAMIC_ZONE_DATA_SCHEMA,
|
SET_DYNAMIC_ZONE_DATA_SCHEMA,
|
||||||
SET_ATTRIBUTE_DATA_SCHEMA,
|
SET_ATTRIBUTE_DATA_SCHEMA,
|
||||||
// ADD_COMPONENTS_TO_DYNAMIC_ZONE,
|
// ADD_COMPONENTS_TO_DYNAMIC_ZONE,
|
||||||
// ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
SET_ERRORS,
|
SET_ERRORS,
|
||||||
ON_CHANGE,
|
ON_CHANGE,
|
||||||
RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ,
|
RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ,
|
||||||
@ -564,14 +564,6 @@ const FormModal = () => {
|
|||||||
// });
|
// });
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// const handleChangeMediaAllowedTypes = ({ target: { name, value } }) => {
|
|
||||||
// dispatch({
|
|
||||||
// type: ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
// name,
|
|
||||||
// value,
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
({ target: { name, value, type, ...rest } }) => {
|
({ target: { name, value, type, ...rest } }) => {
|
||||||
const namesThatCanResetToNullValue = [
|
const namesThatCanResetToNullValue = [
|
||||||
@ -1095,6 +1087,7 @@ const FormModal = () => {
|
|||||||
|
|
||||||
const genericInputProps = {
|
const genericInputProps = {
|
||||||
customInputs: {
|
customInputs: {
|
||||||
|
'allowed-types-select': AllowedTypesSelect,
|
||||||
'checkbox-with-number-field': CheckboxWithNumberField,
|
'checkbox-with-number-field': CheckboxWithNumberField,
|
||||||
'select-default-boolean': BooleanDefaultValueSelect,
|
'select-default-boolean': BooleanDefaultValueSelect,
|
||||||
'radio-group': CustomRadioGroup,
|
'radio-group': CustomRadioGroup,
|
||||||
|
@ -183,40 +183,7 @@ const reducer = (state = initialState, action) =>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case actions.ON_CHANGE_ALLOWED_TYPE: {
|
|
||||||
if (action.name === 'all') {
|
|
||||||
if (action.value) {
|
|
||||||
set(draftState, ['modifiedData', 'allowedTypes'], ['images', 'videos', 'files']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
set(draftState, ['modifiedData', 'allowedTypes'], null);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentList = state.modifiedData.allowedTypes || [];
|
|
||||||
let updatedList = [...currentList];
|
|
||||||
|
|
||||||
if (currentList.includes(action.name)) {
|
|
||||||
updatedList = updatedList.filter(v => v !== action.name);
|
|
||||||
|
|
||||||
if (updatedList.length === 0) {
|
|
||||||
set(draftState, ['modifiedData', 'allowedTypes'], null);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
set(draftState, ['modifiedData', 'allowedTypes'], updatedList);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedList.push(action.name);
|
|
||||||
|
|
||||||
set(draftState, ['modifiedData', 'allowedTypes'], updatedList);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case actions.RESET_PROPS:
|
case actions.RESET_PROPS:
|
||||||
return initialState;
|
return initialState;
|
||||||
case actions.RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO: {
|
case actions.RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO: {
|
||||||
|
@ -141,124 +141,6 @@ describe('CTB | components | FormModal | reducer | actions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ON_CHANGE_ALLOWED_TYPE', () => {
|
|
||||||
it('Should add the missing types', () => {
|
|
||||||
const state = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['images', 'videos'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
name: 'all',
|
|
||||||
value: true,
|
|
||||||
type: actions.ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['images', 'videos', 'files'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should remove the missing types', () => {
|
|
||||||
const state = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['images', 'videos', 'files'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
name: 'all',
|
|
||||||
value: false,
|
|
||||||
type: actions.ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Shoul add the missing type', () => {
|
|
||||||
const state = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['videos', 'files'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
name: 'images',
|
|
||||||
value: null,
|
|
||||||
type: actions.ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['videos', 'files', 'images'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should remove the type', () => {
|
|
||||||
const state = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['videos', 'images', 'files'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
name: 'images',
|
|
||||||
value: null,
|
|
||||||
type: actions.ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['videos', 'files'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should remove set the allowedTypes to null if removing the last type', () => {
|
|
||||||
const state = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: ['videos'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
name: 'videos',
|
|
||||||
value: null,
|
|
||||||
type: actions.ON_CHANGE_ALLOWED_TYPE,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
...initialState,
|
|
||||||
modifiedData: {
|
|
||||||
allowedTypes: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ON_CHANGE_RELATION_TARGET', () => {
|
describe('ON_CHANGE_RELATION_TARGET', () => {
|
||||||
it('Should handle the target change correctly for a one side relation (oneWay, manyWay)', () => {
|
it('Should handle the target change correctly for a one side relation (oneWay, manyWay)', () => {
|
||||||
const state = {
|
const state = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user