Remove old files

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-03 09:41:36 +02:00
parent 7e2f8063a8
commit 57ce9de53a
50 changed files with 0 additions and 1927 deletions

View File

@ -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">
&nbsp;{formatMessage({ id: `components.FilterOptions.FILTER_TYPES.${filter}` })}&nbsp;
</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;

View File

@ -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;

View File

@ -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;

View File

@ -1,8 +0,0 @@
import styled from 'styled-components';
const Wrapper = styled.div`
width: 260px;
padding: 13px 15px;
`;
export default Wrapper;

View File

@ -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;

View File

@ -1,5 +0,0 @@
const init = initialState => {
return initialState;
};
export default init;

View File

@ -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 };

View File

@ -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);
});
});

View File

@ -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);
});
});
});

View File

@ -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;

View File

@ -1,9 +0,0 @@
const getInputValue = (type, value) => {
if (type === 'booleanSelect') {
return value === 'true';
}
return value;
};
export default getInputValue;

View File

@ -1,9 +0,0 @@
const getInputValue = (type, value) => {
if (type === 'booleanSelect') {
return value.toString();
}
return value;
};
export default getInputValue;

View File

@ -1,3 +0,0 @@
export { default as form } from './form';
export { default as formatInputValue } from './formatInputValue';
export { default as getInputValue } from './getInputValue';

View File

@ -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);
});
});
});

View File

@ -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;

View File

@ -1,7 +0,0 @@
import styled from 'styled-components';
const Wrapper = styled.div`
padding: 12px 10px;
`;
export default Wrapper;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,5 +0,0 @@
const init = initialState => {
return initialState;
};
export default init;

View File

@ -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 };

View File

@ -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);
});
});

View File

@ -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);
});
});
});

View File

@ -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;

View File

@ -1,8 +0,0 @@
const formDataModel = {
firstname: '',
lastname: '',
email: '',
roles: [],
};
export default formDataModel;

View File

@ -1,10 +0,0 @@
import RolesSelectComponent from '../../RoleSettingsModalSection/RolesSelectComponent';
const roleSettingsForm = {
roles: {
label: 'Settings.permissions.users.form.firstname',
Component: RolesSelectComponent,
},
};
export default roleSettingsForm;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,3 +0,0 @@
const IndicatorSeparator = () => null;
export default IndicatorSeparator;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
});
});
});

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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';