mirror of
https://github.com/strapi/strapi.git
synced 2025-09-10 09:08:18 +00:00
Remove old files
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
7e2f8063a8
commit
57ce9de53a
@ -1,41 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { Option, Text } from '@buffetjs/core';
|
|
||||||
|
|
||||||
const Filter = ({ displayName, filter, name, onClick, value }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
const label = (
|
|
||||||
<>
|
|
||||||
<Text color="mediumBlue" as="span">
|
|
||||||
{displayName}
|
|
||||||
</Text>
|
|
||||||
<Text as="span" color="mediumBlue" fontWeight="bold">
|
|
||||||
{formatMessage({ id: `components.FilterOptions.FILTER_TYPES.${filter}` })}
|
|
||||||
</Text>
|
|
||||||
<Text as="span" color="mediumBlue">
|
|
||||||
{value}
|
|
||||||
</Text>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
onClick({ target: { name, value } });
|
|
||||||
};
|
|
||||||
|
|
||||||
return <Option label={label} margin="0 10px 6px 0" onClick={handleClick} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
Filter.defaultProps = {
|
|
||||||
onClick: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
Filter.propTypes = {
|
|
||||||
filter: PropTypes.string.isRequired,
|
|
||||||
displayName: PropTypes.string.isRequired,
|
|
||||||
name: PropTypes.string.isRequired,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
value: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Filter;
|
|
@ -1,14 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import { FilterIcon } from '@strapi/helper-plugin';
|
|
||||||
|
|
||||||
const Button = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FilterIcon />
|
|
||||||
<FormattedMessage id="app.utils.filters" />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Button;
|
|
@ -1,35 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { InputText, Select, Toggle } from '@buffetjs/core';
|
|
||||||
import { formatInputValue } from './utils';
|
|
||||||
|
|
||||||
const getInputType = type => {
|
|
||||||
switch (type) {
|
|
||||||
case 'toggle':
|
|
||||||
return Toggle;
|
|
||||||
case 'booleanSelect':
|
|
||||||
return Select;
|
|
||||||
default:
|
|
||||||
return InputText;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Input({ onChange, type, ...rest }) {
|
|
||||||
const Component = getInputType(type);
|
|
||||||
const handleChange = ({ target: { name, value } }) => {
|
|
||||||
onChange({ target: { name, value: formatInputValue(type, value) } });
|
|
||||||
};
|
|
||||||
|
|
||||||
return <Component onChange={handleChange} {...rest} autoComplete="off" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
Input.defaultProps = {
|
|
||||||
onChange: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.propTypes = {
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
type: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Input;
|
|
@ -1,8 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
width: 260px;
|
|
||||||
padding: 13px 15px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Wrapper;
|
|
@ -1,91 +0,0 @@
|
|||||||
import React, { useReducer } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import { Select, Padded } from '@buffetjs/core';
|
|
||||||
import Button from '../../../FullWidthButton';
|
|
||||||
import { form, getInputValue } from './utils';
|
|
||||||
import { initialState, reducer } from './reducer';
|
|
||||||
import init from './init';
|
|
||||||
import Input from './Input';
|
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
|
|
||||||
const Card = ({ onChange }) => {
|
|
||||||
const [
|
|
||||||
{
|
|
||||||
modifiedData: { name, filter, value },
|
|
||||||
},
|
|
||||||
dispatch,
|
|
||||||
] = useReducer(reducer, initialState, init);
|
|
||||||
|
|
||||||
const handleChangeName = ({ target: { value } }) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'ON_CHANGE_NAME',
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = ({ target: { name, value } }) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'ON_CHANGE',
|
|
||||||
keys: name,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderFiltersOptions = () => {
|
|
||||||
return form[name].allowedFilters.map(filter => (
|
|
||||||
<FormattedMessage id={filter.id} key={filter.id}>
|
|
||||||
{msg => <option value={filter.value}>{msg}</option>}
|
|
||||||
</FormattedMessage>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
onChange({ name, filter, value });
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'RESET_FORM',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<Padded bottom size="11px">
|
|
||||||
<Select name="name" onChange={handleChangeName} options={Object.keys(form)} value={name} />
|
|
||||||
</Padded>
|
|
||||||
<Padded bottom size="11px">
|
|
||||||
<Select
|
|
||||||
onChange={handleChange}
|
|
||||||
options={renderFiltersOptions()}
|
|
||||||
name="filter"
|
|
||||||
value={filter}
|
|
||||||
/>
|
|
||||||
</Padded>
|
|
||||||
<Padded bottom size="11px">
|
|
||||||
<Input
|
|
||||||
onChange={handleChange}
|
|
||||||
name="value"
|
|
||||||
type={form[name].type}
|
|
||||||
value={getInputValue(form[name].type, value)}
|
|
||||||
options={[
|
|
||||||
{ label: 'true', value: 'true' },
|
|
||||||
{ label: 'false', value: 'false' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Padded>
|
|
||||||
<Button icon onClick={handleSubmit} type="button">
|
|
||||||
<FormattedMessage id="app.utils.add-filter" />
|
|
||||||
</Button>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Card.defaultProps = {
|
|
||||||
onChange: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
Card.propTypes = {
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Card;
|
|
@ -1,5 +0,0 @@
|
|||||||
const init = initialState => {
|
|
||||||
return initialState;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default init;
|
|
@ -1,39 +0,0 @@
|
|||||||
/* eslint-disable consistent-return */
|
|
||||||
import produce from 'immer';
|
|
||||||
import { get, set } from 'lodash';
|
|
||||||
import form from './utils/form';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'firstname',
|
|
||||||
filter: '',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const reducer = (state, action) =>
|
|
||||||
produce(state, draftState => {
|
|
||||||
switch (action.type) {
|
|
||||||
case 'ON_CHANGE': {
|
|
||||||
set(draftState, ['modifiedData', ...action.keys.split('.')], action.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ON_CHANGE_NAME': {
|
|
||||||
// Change the name
|
|
||||||
set(draftState, ['modifiedData', 'name'], action.value);
|
|
||||||
// Reset the default filter
|
|
||||||
set(draftState, ['modifiedData', 'filter'], '');
|
|
||||||
// Reset the default value
|
|
||||||
const defaultValue = get(form, [action.value, 'defaultValue'], '');
|
|
||||||
set(draftState, ['modifiedData', 'value'], defaultValue);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'RESET_FORM': {
|
|
||||||
return initialState;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return draftState;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export { initialState, reducer };
|
|
@ -1,11 +0,0 @@
|
|||||||
import init from '../init';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USERS | FilterPicker | Card | init', () => {
|
|
||||||
it('should return the initialState', () => {
|
|
||||||
const initialState = {
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(init(initialState)).toEqual(initialState);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,92 +0,0 @@
|
|||||||
import { reducer } from '../reducer';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USERS | FilterPicker | Card | reducer', () => {
|
|
||||||
describe('DEFAULT_ACTION', () => {
|
|
||||||
it('should return the initialState', () => {
|
|
||||||
const initialState = {
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, {})).toEqual(initialState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ON_CHANGE', () => {
|
|
||||||
it('should change the data correctly', () => {
|
|
||||||
const initialState = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'firstname',
|
|
||||||
filter: '',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
type: 'ON_CHANGE',
|
|
||||||
keys: 'filter',
|
|
||||||
value: '_ne',
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'firstname',
|
|
||||||
filter: '_ne',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ON_CHANGE_NAME', () => {
|
|
||||||
it('should change the data correctly', () => {
|
|
||||||
const initialState = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'firstname',
|
|
||||||
filter: '_ne',
|
|
||||||
value: 'test',
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
type: 'ON_CHANGE_NAME',
|
|
||||||
keys: 'name',
|
|
||||||
value: 'isActive',
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'isActive',
|
|
||||||
filter: '',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('RESET_FORM', () => {
|
|
||||||
it('should reset the form correctly', () => {
|
|
||||||
const action = {
|
|
||||||
type: 'RESET_FORM',
|
|
||||||
};
|
|
||||||
const initialState = {
|
|
||||||
test: true,
|
|
||||||
modifiedData: {
|
|
||||||
ok: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
modifiedData: {
|
|
||||||
name: 'firstname',
|
|
||||||
filter: '',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
const textFilters = [
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES.=',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES._ne',
|
|
||||||
value: '_ne',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES._contains',
|
|
||||||
value: '_contains',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES._containss',
|
|
||||||
value: '_containss',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const form = {
|
|
||||||
firstname: {
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: '',
|
|
||||||
allowedFilters: textFilters,
|
|
||||||
},
|
|
||||||
lastname: {
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: '',
|
|
||||||
allowedFilters: textFilters,
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: 'email',
|
|
||||||
defaultValue: '',
|
|
||||||
allowedFilters: textFilters,
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: '',
|
|
||||||
allowedFilters: textFilters,
|
|
||||||
},
|
|
||||||
isActive: {
|
|
||||||
type: 'booleanSelect',
|
|
||||||
defaultValue: true,
|
|
||||||
allowedFilters: [
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES.=',
|
|
||||||
value: '=',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'components.FilterOptions.FILTER_TYPES._ne',
|
|
||||||
value: '_ne',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default form;
|
|
@ -1,9 +0,0 @@
|
|||||||
const getInputValue = (type, value) => {
|
|
||||||
if (type === 'booleanSelect') {
|
|
||||||
return value === 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getInputValue;
|
|
@ -1,9 +0,0 @@
|
|||||||
const getInputValue = (type, value) => {
|
|
||||||
if (type === 'booleanSelect') {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getInputValue;
|
|
@ -1,3 +0,0 @@
|
|||||||
export { default as form } from './form';
|
|
||||||
export { default as formatInputValue } from './formatInputValue';
|
|
||||||
export { default as getInputValue } from './getInputValue';
|
|
@ -1,35 +0,0 @@
|
|||||||
import formatInputValue from '../formatInputValue';
|
|
||||||
import getInputValue from '../getInputValue';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USER | FilterPicker | Card | utils', () => {
|
|
||||||
describe('formatInputValue', () => {
|
|
||||||
it('should return a boolean if the type is booleanSelect', () => {
|
|
||||||
const type = 'booleanSelect';
|
|
||||||
|
|
||||||
expect(formatInputValue(type, 'true')).toBeTruthy();
|
|
||||||
expect(formatInputValue(type, 'false')).toBeFalsy();
|
|
||||||
expect(formatInputValue(type, 'test')).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the value if the type is not booleanSelect', () => {
|
|
||||||
const type = 'test';
|
|
||||||
|
|
||||||
expect(formatInputValue(type, 'true')).toEqual('true');
|
|
||||||
expect(formatInputValue(type, 'false')).toEqual('false');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getInputValue', () => {
|
|
||||||
it('should return a string if the type is booleanSelect', () => {
|
|
||||||
const type = 'booleanSelect';
|
|
||||||
|
|
||||||
expect(getInputValue(type, true)).toEqual('true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the value if the type is not booleanSelect', () => {
|
|
||||||
const type = 'test';
|
|
||||||
|
|
||||||
expect(getInputValue(type, true)).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Picker } from '@buffetjs/core';
|
|
||||||
|
|
||||||
import Button from './Button';
|
|
||||||
import Card from './Card';
|
|
||||||
|
|
||||||
const FilterPicker = ({ onChange }) => {
|
|
||||||
return (
|
|
||||||
<Picker
|
|
||||||
renderButtonContent={Button}
|
|
||||||
renderSectionContent={onToggle => (
|
|
||||||
<Card
|
|
||||||
onChange={({ value, ...rest }) => {
|
|
||||||
if (value !== '') {
|
|
||||||
onChange({ ...rest, value });
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggle();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterPicker.defaultProps = {
|
|
||||||
onChange: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterPicker.propTypes = {
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FilterPicker;
|
|
@ -1,7 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
padding: 12px 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Wrapper;
|
|
@ -1,40 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { PageFooter } from '@strapi/helper-plugin';
|
|
||||||
import { Padded } from '@buffetjs/core';
|
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
|
|
||||||
const Footer = ({ count, onChange, params }) => {
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<Padded left right size="xs">
|
|
||||||
<PageFooter
|
|
||||||
context={{ trackUsage: () => {} }}
|
|
||||||
count={count}
|
|
||||||
onChangeParams={onChange}
|
|
||||||
params={params}
|
|
||||||
/>
|
|
||||||
</Padded>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Footer.defaultProps = {
|
|
||||||
count: 0,
|
|
||||||
onChange: () => {},
|
|
||||||
params: {
|
|
||||||
_limit: 10,
|
|
||||||
_page: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Footer.propTypes = {
|
|
||||||
count: PropTypes.number,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
params: PropTypes.shape({
|
|
||||||
_limit: PropTypes.number,
|
|
||||||
_page: PropTypes.number,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Footer;
|
|
@ -1,20 +0,0 @@
|
|||||||
/* eslint-disable jsx-a11y/accessible-emoji */
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const Envelope = () => (
|
|
||||||
<svg width="24" height="17" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<text
|
|
||||||
transform="translate(-23 -9)"
|
|
||||||
fill="#4B515A"
|
|
||||||
fillRule="evenodd"
|
|
||||||
fontSize="24"
|
|
||||||
fontFamily="AppleColorEmoji, Apple Color Emoji"
|
|
||||||
>
|
|
||||||
<tspan x="23" y="28">
|
|
||||||
✉️
|
|
||||||
</tspan>
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default Envelope;
|
|
@ -1,15 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { Flex } from '@buffetjs/core';
|
|
||||||
|
|
||||||
const IconWrapper = styled(Flex)`
|
|
||||||
height: 100%;
|
|
||||||
margin-right: 18px;
|
|
||||||
transform: rotate(-20deg);
|
|
||||||
`;
|
|
||||||
|
|
||||||
IconWrapper.defaultProps = {
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default IconWrapper;
|
|
@ -1,26 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
height: 68px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
&:before {
|
|
||||||
content: '';
|
|
||||||
width: 5px;
|
|
||||||
height: 100%;
|
|
||||||
margin-right: 16px;
|
|
||||||
background-color: #6dbb1a;
|
|
||||||
border-top-left-radius: ${({ theme }) => theme.main.sizes.borderRadius};
|
|
||||||
border-bottom-left-radius: ${({ theme }) => theme.main.sizes.borderRadius};
|
|
||||||
}
|
|
||||||
border-radius: ${({ theme }) => theme.main.sizes.borderRadius};
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
||||||
|
|
||||||
.icon-duplicate {
|
|
||||||
margin-left: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Wrapper;
|
|
@ -1,50 +0,0 @@
|
|||||||
// This component is a work in progress
|
|
||||||
// It's made to be used when the users API is ready
|
|
||||||
import React from 'react';
|
|
||||||
import { useNotification } from '@strapi/helper-plugin';
|
|
||||||
import { Flex, Text } from '@buffetjs/core';
|
|
||||||
import { Duplicate } from '@buffetjs/icons';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|
||||||
import IconWrapper from './IconWrapper';
|
|
||||||
import Envelope from './Envelope';
|
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
|
|
||||||
const LinkNotification = ({ target, children }) => {
|
|
||||||
const toggleNotification = useNotification();
|
|
||||||
|
|
||||||
const handleCopy = () => {
|
|
||||||
toggleNotification({ type: 'info', message: { id: 'notification.link-copied' } });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<IconWrapper>
|
|
||||||
<Envelope />
|
|
||||||
</IconWrapper>
|
|
||||||
<Flex flexDirection="column" justifyContent="center">
|
|
||||||
<Text fontWeight="semiBold" color="black" fontSize="md" lineHeight="18px">
|
|
||||||
{target}
|
|
||||||
<CopyToClipboard onCopy={handleCopy} text={target}>
|
|
||||||
<Duplicate fill="#8B91A0" className="icon-duplicate" />
|
|
||||||
</CopyToClipboard>
|
|
||||||
</Text>
|
|
||||||
<Text fontWeight="regular" color="grey" fontSize="sm" lineHeight="18px">
|
|
||||||
{children}
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
LinkNotification.defaultProps = {
|
|
||||||
target: '',
|
|
||||||
children: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
LinkNotification.propTypes = {
|
|
||||||
target: PropTypes.string,
|
|
||||||
children: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LinkNotification;
|
|
@ -1,27 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import LinkNotification from '../LinkNotification';
|
|
||||||
import basename from '../../../core/utils/basename';
|
|
||||||
|
|
||||||
const MagicLink = ({ registrationToken }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
|
|
||||||
const link = `${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LinkNotification target={link}>
|
|
||||||
{formatMessage({ id: 'app.components.Users.MagicLink.connect' })}
|
|
||||||
</LinkNotification>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
MagicLink.defaultProps = {
|
|
||||||
registrationToken: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
MagicLink.propTypes = {
|
|
||||||
registrationToken: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MagicLink;
|
|
@ -1,12 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { Container } from 'reactstrap';
|
|
||||||
|
|
||||||
const Wrapper = styled(Container)`
|
|
||||||
padding: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
Wrapper.defaultProps = {
|
|
||||||
fluid: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Wrapper;
|
|
@ -1,162 +0,0 @@
|
|||||||
import React, { forwardRef, useReducer, useImperativeHandle, useRef } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
|
||||||
BaselineAlignment,
|
|
||||||
ModalSection,
|
|
||||||
request,
|
|
||||||
useNotification,
|
|
||||||
useOverlayBlocker,
|
|
||||||
} from '@strapi/helper-plugin';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { get } from 'lodash';
|
|
||||||
import { Padded, Text } from '@buffetjs/core';
|
|
||||||
import { Row } from 'reactstrap';
|
|
||||||
import MagicLink from 'ee_else_ce/components/Users/MagicLink';
|
|
||||||
|
|
||||||
import checkFormValidity from '../../../utils/checkFormValidity';
|
|
||||||
import form from './utils/form';
|
|
||||||
import schema from './utils/schema';
|
|
||||||
import { initialState, reducer } from './reducer';
|
|
||||||
import init from './init';
|
|
||||||
import Input from '../../SizedInput';
|
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
import RoleSettingsModalSection from '../RoleSettingsModalSection';
|
|
||||||
|
|
||||||
// This component accepts a ref so we can have access to the submit handler.
|
|
||||||
const ModalCreateBody = forwardRef(
|
|
||||||
({ isDisabled, onSubmit, registrationToken, setIsSubmiting, showMagicLink }, ref) => {
|
|
||||||
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
||||||
|
|
||||||
const toggleNotification = useNotification();
|
|
||||||
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
|
||||||
const { formErrors, modifiedData } = reducerState;
|
|
||||||
const buttonSubmitRef = useRef(null);
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
submit: () => {
|
|
||||||
buttonSubmitRef.current.click();
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const handleChange = ({ target: { name, value } }) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'ON_CHANGE',
|
|
||||||
keys: name,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async e => {
|
|
||||||
e.persist();
|
|
||||||
e.preventDefault();
|
|
||||||
const errors = await checkFormValidity(modifiedData, schema);
|
|
||||||
|
|
||||||
if (!errors) {
|
|
||||||
try {
|
|
||||||
// Prevent user interactions until the request is completed
|
|
||||||
lockApp();
|
|
||||||
|
|
||||||
setIsSubmiting(true);
|
|
||||||
|
|
||||||
const requestURL = '/admin/users';
|
|
||||||
const cleanedRoles = modifiedData.roles.map(role => role.id);
|
|
||||||
|
|
||||||
const { data } = await request(requestURL, {
|
|
||||||
method: 'POST',
|
|
||||||
body: { ...modifiedData, roles: cleanedRoles },
|
|
||||||
});
|
|
||||||
|
|
||||||
onSubmit(e, data);
|
|
||||||
} catch (err) {
|
|
||||||
const message = get(err, ['response', 'payload', 'message'], 'An error occured');
|
|
||||||
|
|
||||||
toggleNotification({ type: 'warning', message });
|
|
||||||
} finally {
|
|
||||||
unlockApp();
|
|
||||||
setIsSubmiting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'SET_ERRORS',
|
|
||||||
errors: errors || {},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
{showMagicLink && (
|
|
||||||
<>
|
|
||||||
<BaselineAlignment top size="18px" />
|
|
||||||
<ModalSection>
|
|
||||||
<MagicLink registrationToken={registrationToken} />
|
|
||||||
</ModalSection>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<ModalSection>
|
|
||||||
<Padded top size="18px">
|
|
||||||
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
|
|
||||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.details' })}
|
|
||||||
</Text>
|
|
||||||
</Padded>
|
|
||||||
</ModalSection>
|
|
||||||
<ModalSection>
|
|
||||||
<Wrapper>
|
|
||||||
<Padded top size="smd">
|
|
||||||
<Row>
|
|
||||||
{Object.keys(form).map((inputName, i) => (
|
|
||||||
<Input
|
|
||||||
key={inputName}
|
|
||||||
{...form[inputName]}
|
|
||||||
autoFocus={i === 0}
|
|
||||||
disabled={isDisabled}
|
|
||||||
error={formErrors[inputName]}
|
|
||||||
name={inputName}
|
|
||||||
onChange={handleChange}
|
|
||||||
value={modifiedData[inputName]}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
</Padded>
|
|
||||||
</Wrapper>
|
|
||||||
</ModalSection>
|
|
||||||
<ModalSection>
|
|
||||||
<Padded top size="3px">
|
|
||||||
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
|
|
||||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.login' })}
|
|
||||||
</Text>
|
|
||||||
</Padded>
|
|
||||||
</ModalSection>
|
|
||||||
<RoleSettingsModalSection
|
|
||||||
hasSSORegistration={modifiedData.useSSORegistration}
|
|
||||||
modifiedData={modifiedData}
|
|
||||||
onChange={handleChange}
|
|
||||||
formErrors={formErrors}
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
/>
|
|
||||||
<button type="submit" style={{ display: 'none' }} ref={buttonSubmitRef}>
|
|
||||||
hidden button to use the native form event
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ModalCreateBody.defaultProps = {
|
|
||||||
isDisabled: false,
|
|
||||||
onSubmit: e => e.preventDefault(),
|
|
||||||
registrationToken: '',
|
|
||||||
setIsSubmiting: () => {},
|
|
||||||
showMagicLink: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
ModalCreateBody.propTypes = {
|
|
||||||
isDisabled: PropTypes.bool,
|
|
||||||
onSubmit: PropTypes.func,
|
|
||||||
registrationToken: PropTypes.string,
|
|
||||||
setIsSubmiting: PropTypes.func,
|
|
||||||
showMagicLink: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModalCreateBody;
|
|
@ -1,5 +0,0 @@
|
|||||||
const init = initialState => {
|
|
||||||
return initialState;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default init;
|
|
@ -1,27 +0,0 @@
|
|||||||
/* eslint-disable consistent-return */
|
|
||||||
import produce from 'immer';
|
|
||||||
import { set } from 'lodash';
|
|
||||||
import formDataModel from 'ee_else_ce/components/Users/ModalCreateBody/utils/formDataModel';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
formErrors: {},
|
|
||||||
modifiedData: formDataModel,
|
|
||||||
};
|
|
||||||
|
|
||||||
const reducer = (state, action) =>
|
|
||||||
produce(state, draftState => {
|
|
||||||
switch (action.type) {
|
|
||||||
case 'ON_CHANGE': {
|
|
||||||
set(draftState.modifiedData, action.keys.split('.'), action.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_ERRORS': {
|
|
||||||
draftState.formErrors = action.errors;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return draftState;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export { initialState, reducer };
|
|
@ -1,11 +0,0 @@
|
|||||||
import init from '../init';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USERS | MODALCREATEBODY | init', () => {
|
|
||||||
it('should return the initialState', () => {
|
|
||||||
const initialState = {
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(init(initialState)).toEqual(initialState);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,74 +0,0 @@
|
|||||||
import { reducer } from '../reducer';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USERS | MODALCREATEBODY | reducer', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.resetModules();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('DEFAULT_ACTION', () => {
|
|
||||||
it('should return the initialState', () => {
|
|
||||||
const initialState = {
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, {})).toEqual(initialState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ON_CHANGE', () => {
|
|
||||||
it('should change the data correctly', () => {
|
|
||||||
const initialState = {
|
|
||||||
modifiedData: {
|
|
||||||
firstname: 'kai',
|
|
||||||
lastname: '',
|
|
||||||
email: 'kai@strapi.io',
|
|
||||||
roles: [1],
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
const action = {
|
|
||||||
type: 'ON_CHANGE',
|
|
||||||
keys: 'lastname',
|
|
||||||
value: 'doe',
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
modifiedData: {
|
|
||||||
firstname: 'kai',
|
|
||||||
lastname: 'doe',
|
|
||||||
email: 'kai@strapi.io',
|
|
||||||
roles: [1],
|
|
||||||
},
|
|
||||||
test: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('SET_ERRORS', () => {
|
|
||||||
it('Should set the formErrors object correctly', () => {
|
|
||||||
const action = {
|
|
||||||
type: 'SET_ERRORS',
|
|
||||||
errors: {
|
|
||||||
test: 'this is required',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const initialState = {
|
|
||||||
formErrors: {},
|
|
||||||
modifiedData: {
|
|
||||||
ok: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
formErrors: {
|
|
||||||
test: 'this is required',
|
|
||||||
},
|
|
||||||
modifiedData: {
|
|
||||||
ok: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(initialState, action)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,29 +0,0 @@
|
|||||||
const form = {
|
|
||||||
firstname: {
|
|
||||||
autoFocus: true,
|
|
||||||
label: 'Settings.permissions.users.form.firstname',
|
|
||||||
placeholder: 'e.g. Kai',
|
|
||||||
type: 'text',
|
|
||||||
validations: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lastname: {
|
|
||||||
label: 'Settings.permissions.users.form.lastname',
|
|
||||||
placeholder: 'e.g. Doe',
|
|
||||||
type: 'text',
|
|
||||||
validations: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
label: 'Settings.permissions.users.form.email',
|
|
||||||
placeholder: 'e.g. kai.doe@strapi.io',
|
|
||||||
type: 'email',
|
|
||||||
validations: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default form;
|
|
@ -1,8 +0,0 @@
|
|||||||
const formDataModel = {
|
|
||||||
firstname: '',
|
|
||||||
lastname: '',
|
|
||||||
email: '',
|
|
||||||
roles: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default formDataModel;
|
|
@ -1,10 +0,0 @@
|
|||||||
import RolesSelectComponent from '../../RoleSettingsModalSection/RolesSelectComponent';
|
|
||||||
|
|
||||||
const roleSettingsForm = {
|
|
||||||
roles: {
|
|
||||||
label: 'Settings.permissions.users.form.firstname',
|
|
||||||
Component: RolesSelectComponent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default roleSettingsForm;
|
|
@ -1,17 +0,0 @@
|
|||||||
import * as yup from 'yup';
|
|
||||||
import { translatedErrors } from '@strapi/helper-plugin';
|
|
||||||
|
|
||||||
const schema = yup.object().shape({
|
|
||||||
firstname: yup.string().required(translatedErrors.required),
|
|
||||||
lastname: yup.string().required(translatedErrors.required),
|
|
||||||
email: yup
|
|
||||||
.string()
|
|
||||||
.email(translatedErrors.email)
|
|
||||||
.required(translatedErrors.required),
|
|
||||||
roles: yup
|
|
||||||
.array()
|
|
||||||
.min(1, translatedErrors.min)
|
|
||||||
.required(translatedErrors.required),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default schema;
|
|
@ -1,53 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { Padded } from '@buffetjs/core';
|
|
||||||
import { Label, Description as BaseDescription } from '@buffetjs/styles';
|
|
||||||
import { Col } from 'reactstrap';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import SelectRoles from '../SelectRoles';
|
|
||||||
|
|
||||||
const Description = styled(BaseDescription)`
|
|
||||||
font-size: ${({ theme }) => theme.main.sizes.fonts.md};
|
|
||||||
line-height: normal;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const RolesSelectComponent = ({ isDisabled, value, error, onChange }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Col xs="6">
|
|
||||||
<Padded bottom size="xs">
|
|
||||||
<Label style={{ display: 'block' }} htmlFor="roles">
|
|
||||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.roles' })}
|
|
||||||
</Label>
|
|
||||||
</Padded>
|
|
||||||
<SelectRoles
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
name="roles"
|
|
||||||
onChange={onChange}
|
|
||||||
value={value}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
<Description>
|
|
||||||
{formatMessage({
|
|
||||||
id: 'app.components.Users.ModalCreateBody.block-title.roles.description',
|
|
||||||
})}
|
|
||||||
</Description>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
RolesSelectComponent.defaultProps = {
|
|
||||||
value: null,
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
RolesSelectComponent.propTypes = {
|
|
||||||
isDisabled: PropTypes.bool.isRequired,
|
|
||||||
value: PropTypes.array,
|
|
||||||
error: PropTypes.object,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RolesSelectComponent;
|
|
@ -1,76 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { ModalSection } from '@strapi/helper-plugin';
|
|
||||||
import { Padded } from '@buffetjs/core';
|
|
||||||
import { Row } from 'reactstrap';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import roleSettingsForm from 'ee_else_ce/components/Users/ModalCreateBody/utils/roleSettingsForm';
|
|
||||||
|
|
||||||
import Input from '../../SizedInput';
|
|
||||||
import Wrapper from '../ModalCreateBody/Wrapper';
|
|
||||||
|
|
||||||
const RoleSettingsModalSection = ({ isDisabled, modifiedData, onChange, formErrors }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalSection>
|
|
||||||
<Wrapper>
|
|
||||||
<Padded top size="smd">
|
|
||||||
<Row>
|
|
||||||
{Object.keys(roleSettingsForm).map(inputName => {
|
|
||||||
const value = modifiedData[inputName];
|
|
||||||
const { description, type, Component } = roleSettingsForm[inputName];
|
|
||||||
const error = formErrors[inputName];
|
|
||||||
|
|
||||||
if (Component) {
|
|
||||||
return (
|
|
||||||
<Component
|
|
||||||
key={inputName}
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
error={error}
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Input
|
|
||||||
{...roleSettingsForm[inputName]}
|
|
||||||
key={inputName}
|
|
||||||
description={formatMessage({ id: description })}
|
|
||||||
type={type}
|
|
||||||
disabled={isDisabled}
|
|
||||||
name={inputName}
|
|
||||||
onChange={onChange}
|
|
||||||
value={modifiedData.useSSORegistration}
|
|
||||||
error={formErrors.useSSORegistration}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Row>
|
|
||||||
</Padded>
|
|
||||||
</Wrapper>
|
|
||||||
</ModalSection>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
RoleSettingsModalSection.defaultProps = {
|
|
||||||
isDisabled: false,
|
|
||||||
formErrors: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
RoleSettingsModalSection.propTypes = {
|
|
||||||
isDisabled: PropTypes.bool,
|
|
||||||
modifiedData: PropTypes.shape({
|
|
||||||
roles: PropTypes.array,
|
|
||||||
useSSORegistration: PropTypes.bool,
|
|
||||||
}).isRequired,
|
|
||||||
formErrors: PropTypes.shape({
|
|
||||||
roles: PropTypes.object,
|
|
||||||
useSSORegistration: PropTypes.bool,
|
|
||||||
}),
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RoleSettingsModalSection;
|
|
@ -1,15 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Remove } from '@buffetjs/icons';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
|
|
||||||
const ClearIndicator = props => {
|
|
||||||
const Component = components.ClearIndicator;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Component {...props}>
|
|
||||||
<Remove width="11px" height="11px" fill="#9EA7B8" />
|
|
||||||
</Component>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ClearIndicator;
|
|
@ -1,39 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { Flex } from '@buffetjs/core';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const Wrapper = styled(Flex)`
|
|
||||||
height: 100%;
|
|
||||||
width: 32px;
|
|
||||||
background: #fafafb;
|
|
||||||
> svg {
|
|
||||||
align-self: center;
|
|
||||||
font-size: 11px;
|
|
||||||
color: #b3b5b9;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DropdownIndicator = ({ selectProps: { menuIsOpen } }) => {
|
|
||||||
const icon = menuIsOpen ? 'caret-up' : 'caret-down';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<FontAwesomeIcon icon={icon} />
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
DropdownIndicator.propTypes = {
|
|
||||||
selectProps: PropTypes.shape({
|
|
||||||
menuIsOpen: PropTypes.bool.isRequired,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
Wrapper.defaultProps = {
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DropdownIndicator;
|
|
@ -1,10 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { ErrorMessage as Base } from '@buffetjs/styles';
|
|
||||||
|
|
||||||
const ErrorMessage = styled(Base)`
|
|
||||||
padding-top: 11px;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin-bottom: 17px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default ErrorMessage;
|
|
@ -1,3 +0,0 @@
|
|||||||
const IndicatorSeparator = () => null;
|
|
||||||
|
|
||||||
export default IndicatorSeparator;
|
|
@ -1,43 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import StyledOption from './StyledOption';
|
|
||||||
|
|
||||||
const MultiValueContainer = ({ data, selectProps }) => {
|
|
||||||
const Component = components.MultiValueContainer;
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
const newValue = selectProps.value.filter(option => option.id !== data.id);
|
|
||||||
|
|
||||||
selectProps.onChange(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Component {...data} {...selectProps}>
|
|
||||||
<StyledOption
|
|
||||||
label={data.name}
|
|
||||||
height="24px"
|
|
||||||
lineHeight="26px"
|
|
||||||
margin="2px 5px 0px 0"
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
</Component>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
MultiValueContainer.defaultProps = {
|
|
||||||
data: {},
|
|
||||||
selectProps: {
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
MultiValueContainer.propTypes = {
|
|
||||||
data: PropTypes.object,
|
|
||||||
selectProps: PropTypes.shape({
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
value: PropTypes.array,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MultiValueContainer;
|
|
@ -1,11 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { Option } from '@buffetjs/core';
|
|
||||||
|
|
||||||
const StyledOption = styled(Option)`
|
|
||||||
> span {
|
|
||||||
display: block !important;
|
|
||||||
color: #007eff !important;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default StyledOption;
|
|
@ -1,68 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Select from 'react-select';
|
|
||||||
import { Padded } from '@buffetjs/core';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { useRolesList } from '../../../hooks';
|
|
||||||
import styles from './utils/styles';
|
|
||||||
import ClearIndicator from './ClearIndicator';
|
|
||||||
import DropdownIndicator from './DropdownIndicator';
|
|
||||||
import ErrorMessage from './ErrorMessage';
|
|
||||||
import IndicatorSeparator from './IndicatorSeparator';
|
|
||||||
import MultiValueContainer from './MultiValueContainer';
|
|
||||||
|
|
||||||
const SelectRoles = ({ error, isDisabled, name, onChange, value }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
const translatedError = error && error.id ? formatMessage(error) : null;
|
|
||||||
const { roles: data, isLoading } = useRolesList();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Select
|
|
||||||
name={name}
|
|
||||||
components={{
|
|
||||||
ClearIndicator,
|
|
||||||
DropdownIndicator,
|
|
||||||
IndicatorSeparator,
|
|
||||||
MultiValueContainer,
|
|
||||||
}}
|
|
||||||
error={error}
|
|
||||||
getOptionLabel={option => option.name}
|
|
||||||
getOptionValue={option => option.id}
|
|
||||||
onChange={data => {
|
|
||||||
onChange({ target: { name, value: data } });
|
|
||||||
}}
|
|
||||||
isClearable
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
isLoading={isLoading}
|
|
||||||
isMulti
|
|
||||||
options={isLoading ? [] : data}
|
|
||||||
styles={styles}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
{error && value.length === 0 ? (
|
|
||||||
<ErrorMessage>{translatedError}</ErrorMessage>
|
|
||||||
) : (
|
|
||||||
<Padded top size="11px" />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
SelectRoles.defaultProps = {
|
|
||||||
error: null,
|
|
||||||
isDisabled: false,
|
|
||||||
value: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
SelectRoles.propTypes = {
|
|
||||||
error: PropTypes.shape({
|
|
||||||
id: PropTypes.string,
|
|
||||||
}),
|
|
||||||
isDisabled: PropTypes.bool,
|
|
||||||
name: PropTypes.string.isRequired,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
value: PropTypes.array,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SelectRoles;
|
|
@ -1,99 +0,0 @@
|
|||||||
/* eslint-disable indent */
|
|
||||||
/* eslint-disable no-nested-ternary */
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
control: (base, state) => {
|
|
||||||
const borderRadiusStyle = state.selectProps.menuIsOpen
|
|
||||||
? {
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
}
|
|
||||||
: {};
|
|
||||||
|
|
||||||
const {
|
|
||||||
selectProps: { error, value },
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
let border;
|
|
||||||
let borderBottom;
|
|
||||||
let backgroundColor;
|
|
||||||
|
|
||||||
if (state.isFocused) {
|
|
||||||
border = '1px solid #78caff !important';
|
|
||||||
} else if (error && !value.length) {
|
|
||||||
border = '1px solid #f64d0a !important';
|
|
||||||
} else {
|
|
||||||
border = '1px solid #e3e9f3 !important';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.menuIsOpen === true) {
|
|
||||||
borderBottom = '1px solid #e3e9f3 !important';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.isDisabled) {
|
|
||||||
backgroundColor = '#fafafb !important';
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...base,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
border,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
...borderRadiusStyle,
|
|
||||||
borderBottom,
|
|
||||||
backgroundColor,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
menu: base => {
|
|
||||||
return {
|
|
||||||
...base,
|
|
||||||
width: 'calc(100% - 0px)',
|
|
||||||
margin: '0',
|
|
||||||
paddingTop: 0,
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderTopLeftRadius: '0 !important',
|
|
||||||
borderTopRightRadius: '0 !important',
|
|
||||||
border: '1px solid #78caff !important',
|
|
||||||
boxShadow: 0,
|
|
||||||
borderTop: '0 !important',
|
|
||||||
fontSize: '13px',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
menuList: base => ({
|
|
||||||
...base,
|
|
||||||
maxHeight: '112px',
|
|
||||||
paddingTop: 2,
|
|
||||||
}),
|
|
||||||
option: (base, state) => {
|
|
||||||
return {
|
|
||||||
...base,
|
|
||||||
height: 36,
|
|
||||||
|
|
||||||
backgroundColor: state.isFocused ? '#f6f6f6' : '#fff',
|
|
||||||
':active': {
|
|
||||||
...base[':active'],
|
|
||||||
backgroundColor: '#f6f6f6',
|
|
||||||
},
|
|
||||||
WebkitFontSmoothing: 'antialiased',
|
|
||||||
color: '#333740',
|
|
||||||
fontWeight: state.isFocused ? '600' : '400',
|
|
||||||
cursor: 'pointer',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
placeholder: base => ({
|
|
||||||
...base,
|
|
||||||
marginTop: 0,
|
|
||||||
marginLeft: 8,
|
|
||||||
color: '#aaa',
|
|
||||||
}),
|
|
||||||
valueContainer: base => ({
|
|
||||||
...base,
|
|
||||||
padding: '2px 4px 4px 4px',
|
|
||||||
lineHeight: '18px',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default styles;
|
|
@ -1,300 +0,0 @@
|
|||||||
import styles from '../styles';
|
|
||||||
|
|
||||||
describe('ADMIN | COMPONENTS | USER | SelectRoles | utils | styles', () => {
|
|
||||||
describe('control', () => {
|
|
||||||
describe('menuIsOpen is equal to true', () => {
|
|
||||||
it('should return the correct border-radius', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: false,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: true,
|
|
||||||
error: null,
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #e3e9f3 !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct border when the component is focused', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: true,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: true,
|
|
||||||
error: null,
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #78caff !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct border when the component is focused and has a value', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: true,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: true,
|
|
||||||
error: null,
|
|
||||||
value: ['test'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #78caff !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct border when the component is focused, has a value and has an error', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: true,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: true,
|
|
||||||
error: true,
|
|
||||||
value: ['test'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #78caff !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct border when the component is not focused, does not have a value and has an error', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: false,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: true,
|
|
||||||
error: true,
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #f64d0a !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderBottomLeftRadius: '0 !important',
|
|
||||||
borderBottomRightRadius: '0 !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('menuIsOpen is false', () => {
|
|
||||||
it('should return the correct border-radius', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: false,
|
|
||||||
selectProps: {
|
|
||||||
menuIsOpen: false,
|
|
||||||
error: null,
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
fontSize: 13,
|
|
||||||
minHeight: 34,
|
|
||||||
outline: 0,
|
|
||||||
boxShadow: 0,
|
|
||||||
border: '1px solid #e3e9f3 !important',
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.control(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('menu', () => {
|
|
||||||
it('should return the correct object', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
width: 'calc(100% - 0px)',
|
|
||||||
margin: '0',
|
|
||||||
paddingTop: 0,
|
|
||||||
borderRadius: '2px !important',
|
|
||||||
borderTopLeftRadius: '0 !important',
|
|
||||||
borderTopRightRadius: '0 !important',
|
|
||||||
border: '1px solid #78caff !important',
|
|
||||||
boxShadow: 0,
|
|
||||||
borderTop: '0 !important',
|
|
||||||
fontSize: '13px',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.menu(base)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('menuList', () => {
|
|
||||||
it('should return the correct object', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
maxHeight: '112px',
|
|
||||||
paddingTop: 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.menuList(base)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('option', () => {
|
|
||||||
it('should return the correct object when it is focused', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
':active': {
|
|
||||||
ok: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: true,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
height: 36,
|
|
||||||
backgroundColor: '#f6f6f6',
|
|
||||||
color: '#333740',
|
|
||||||
fontWeight: '600',
|
|
||||||
WebkitFontSmoothing: 'antialiased',
|
|
||||||
':active': {
|
|
||||||
ok: true,
|
|
||||||
backgroundColor: '#f6f6f6',
|
|
||||||
},
|
|
||||||
cursor: 'pointer',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.option(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct object when it is not focused', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
':active': {
|
|
||||||
ok: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const state = {
|
|
||||||
isFocused: false,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
height: 36,
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
color: '#333740',
|
|
||||||
fontWeight: '400',
|
|
||||||
WebkitFontSmoothing: 'antialiased',
|
|
||||||
':active': {
|
|
||||||
ok: true,
|
|
||||||
backgroundColor: '#f6f6f6',
|
|
||||||
},
|
|
||||||
cursor: 'pointer',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.option(base, state)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('placeholder', () => {
|
|
||||||
it('should return the correct object', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
marginTop: 0,
|
|
||||||
marginLeft: 8,
|
|
||||||
color: '#aaa',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.placeholder(base)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('valueContainer', () => {
|
|
||||||
it('should return the correct object', () => {
|
|
||||||
const base = {
|
|
||||||
ok: true,
|
|
||||||
};
|
|
||||||
const expected = {
|
|
||||||
ok: true,
|
|
||||||
padding: '2px 4px 4px 4px',
|
|
||||||
lineHeight: '18px',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(styles.valueContainer(base)).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,14 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import { Carret } from '@strapi/helper-plugin';
|
|
||||||
|
|
||||||
const Button = isOpen => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FormattedMessage id="app.components.Users.SortPicker.button-label" />
|
|
||||||
<Carret isUp={isOpen} fill={isOpen ? '#007eff' : '#292b2c'} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Button;
|
|
@ -1,46 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import ListItem from './ListItem';
|
|
||||||
import ListWrapper from './ListWrapper';
|
|
||||||
|
|
||||||
const sortOptions = {
|
|
||||||
email_asc: 'email:ASC',
|
|
||||||
email_desc: 'email:DESC',
|
|
||||||
firstname_asc: 'firstname:ASC',
|
|
||||||
firstname_desc: 'firstname:DESC',
|
|
||||||
lastname_asc: 'lastname:ASC',
|
|
||||||
lastname_desc: 'lastname:DESC',
|
|
||||||
username_asc: 'username:ASC',
|
|
||||||
username_desc: 'username:DESC',
|
|
||||||
};
|
|
||||||
|
|
||||||
const SortList = ({ onClick, selectedItem }) => {
|
|
||||||
return (
|
|
||||||
<ListWrapper>
|
|
||||||
{Object.keys(sortOptions).map(item => {
|
|
||||||
return (
|
|
||||||
<ListItem
|
|
||||||
key={item}
|
|
||||||
label={item}
|
|
||||||
value={sortOptions[item]}
|
|
||||||
onClick={onClick}
|
|
||||||
selectedItem={selectedItem}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ListWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
SortList.defaultProps = {
|
|
||||||
onClick: () => {},
|
|
||||||
selectedItem: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
SortList.propTypes = {
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
selectedItem: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SortList;
|
|
@ -1,37 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Text } from '@buffetjs/core';
|
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import StyledListItem from './StyledListItem';
|
|
||||||
|
|
||||||
const ListItem = ({ onClick, selectedItem, label, value }) => {
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
onClick({ target: { name: 'sort', value } });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledListItem isActive={selectedItem === value} onClick={handleClick}>
|
|
||||||
<Text lineHeight="27px">
|
|
||||||
{formatMessage({ id: `app.components.Users.SortPicker.sortby.${label}` })}
|
|
||||||
</Text>
|
|
||||||
</StyledListItem>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ListItem.defaultProps = {
|
|
||||||
selectedItem: null,
|
|
||||||
label: '',
|
|
||||||
onClick: () => {},
|
|
||||||
value: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
ListItem.propTypes = {
|
|
||||||
selectedItem: PropTypes.string,
|
|
||||||
label: PropTypes.string,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
value: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ListItem;
|
|
@ -1,18 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { themePropTypes } from '@strapi/helper-plugin';
|
|
||||||
import { Text } from '@buffetjs/core';
|
|
||||||
|
|
||||||
const ListWrapper = styled(props => <Text as="ul" fontSize="md" {...props} />)`
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding: 0;
|
|
||||||
min-width: 230px;
|
|
||||||
list-style-type: none;
|
|
||||||
background-color: ${({ theme }) => theme.main.colors.white};
|
|
||||||
`;
|
|
||||||
|
|
||||||
ListWrapper.propTypes = {
|
|
||||||
...themePropTypes,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ListWrapper;
|
|
@ -1,30 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { themePropTypes } from '@strapi/helper-plugin';
|
|
||||||
|
|
||||||
/* eslint-disable indent */
|
|
||||||
|
|
||||||
const StyledListItem = styled.li`
|
|
||||||
padding: 0 14px;
|
|
||||||
height: 27px;
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: ${({ theme }) => theme.main.colors.mediumGrey};
|
|
||||||
}
|
|
||||||
${({ isActive, theme }) =>
|
|
||||||
isActive &&
|
|
||||||
`
|
|
||||||
background-color: ${theme.main.colors.mediumGrey};
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
StyledListItem.defaultProps = {
|
|
||||||
isActive: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
StyledListItem.propTypes = {
|
|
||||||
isActive: PropTypes.bool,
|
|
||||||
...themePropTypes,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StyledListItem;
|
|
@ -1,34 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Picker } from '@buffetjs/core';
|
|
||||||
import Button from './Button';
|
|
||||||
import List from './List';
|
|
||||||
|
|
||||||
const SortPicker = ({ onChange, value }) => {
|
|
||||||
return (
|
|
||||||
<Picker
|
|
||||||
renderButtonContent={Button}
|
|
||||||
renderSectionContent={onToggle => (
|
|
||||||
<List
|
|
||||||
selectedItem={value}
|
|
||||||
onClick={e => {
|
|
||||||
onChange(e);
|
|
||||||
onToggle();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
SortPicker.defaultProps = {
|
|
||||||
onChange: () => {},
|
|
||||||
value: 'firstname:ASC',
|
|
||||||
};
|
|
||||||
|
|
||||||
SortPicker.propTypes = {
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
value: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SortPicker;
|
|
@ -1,7 +0,0 @@
|
|||||||
// export { default as MagicLink } from './MagicLink';
|
|
||||||
// export { default as Filter } from './Filter';
|
|
||||||
// export { default as Footer } from './Footer';
|
|
||||||
// export { default as FilterPicker } from './FilterPicker';
|
|
||||||
// export { default as SortPicker } from './SortPicker';
|
|
||||||
// export { default as SelectRoles } from './SelectRoles';
|
|
||||||
// export { default as ModalCreateBody } from './ModalCreateBody';
|
|
Loading…
x
Reference in New Issue
Block a user