mirror of
https://github.com/strapi/strapi.git
synced 2025-09-13 18:47:15 +00:00
Disable conditions in EE
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
c08dadaa50
commit
c3147e90c2
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import IS_DISABLED from 'ee_else_ce/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/constants';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import { Flex } from '@strapi/design-system/Flex';
|
||||
import { TableLabel } from '@strapi/design-system/Text';
|
||||
@ -95,7 +96,7 @@ const ActionRow = ({
|
||||
onChange={handleChange}
|
||||
value={values}
|
||||
options={options}
|
||||
disabled={isFormDisabled}
|
||||
disabled={isFormDisabled || IS_DISABLED}
|
||||
/>
|
||||
</Box>
|
||||
</FlexWrapper>
|
||||
|
@ -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,3 +0,0 @@
|
||||
const IndicatorSeparator = () => null;
|
||||
|
||||
export default IndicatorSeparator;
|
@ -1,48 +0,0 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { Collapse } from 'reactstrap';
|
||||
|
||||
const ToggleUl = styled(Collapse)`
|
||||
font-size: 13px;
|
||||
padding: 12px 15px 0 15px;
|
||||
list-style: none;
|
||||
background-color: #fff;
|
||||
> li {
|
||||
padding-top: 5px;
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.check-wrapper {
|
||||
z-index: 9;
|
||||
> input {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
> li:not(:last-child) {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SubUl = ({ children, isOpen }) => {
|
||||
return (
|
||||
<ToggleUl tag="ul" isOpen={isOpen}>
|
||||
{children}
|
||||
</ToggleUl>
|
||||
);
|
||||
};
|
||||
|
||||
SubUl.defaultProps = {
|
||||
children: null,
|
||||
isOpen: false,
|
||||
};
|
||||
|
||||
SubUl.propTypes = {
|
||||
children: PropTypes.node,
|
||||
isOpen: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default SubUl;
|
@ -1,80 +0,0 @@
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Ul = styled.ul`
|
||||
max-height: 150px;
|
||||
font-size: 13px;
|
||||
padding: 0 15px;
|
||||
margin-bottom: 0px;
|
||||
list-style: none;
|
||||
background-color: #fff;
|
||||
> li {
|
||||
label {
|
||||
flex-shrink: 1;
|
||||
width: fit-content !important;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.check-wrapper {
|
||||
z-index: 9;
|
||||
> input {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
.chevron {
|
||||
margin: auto;
|
||||
|
||||
font-size: 11px;
|
||||
color: #919bae;
|
||||
}
|
||||
}
|
||||
.li-multi-menu {
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.li {
|
||||
line-height: 27px;
|
||||
position: relative;
|
||||
> p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> p::after {
|
||||
content: attr(datadescr);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: ${({ theme }) => theme.main.colors.mediumBlue};
|
||||
font-weight: 700;
|
||||
z-index: 100;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: -30px;
|
||||
right: -30px;
|
||||
bottom: 0;
|
||||
background-color: ${({ theme }) => theme.main.colors.lightBlue};
|
||||
}
|
||||
}
|
||||
}
|
||||
${({ disabled, theme }) =>
|
||||
disabled &&
|
||||
`
|
||||
label {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
input[type='checkbox'] {
|
||||
cursor: not-allowed;
|
||||
&:after {
|
||||
cursor: not-allowed;
|
||||
color: ${theme.main.colors.grey};
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
export default Ul;
|
@ -1,6 +0,0 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
|
||||
const UpperFirst = ({ content }) => upperFirst(content);
|
||||
|
||||
export default UpperFirst;
|
@ -1,140 +0,0 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { components } from 'react-select';
|
||||
import { get } from 'lodash';
|
||||
import { Checkbox, Flex } from '@buffetjs/core';
|
||||
import { Label } from '@buffetjs/styles';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import IS_DISABLED from 'ee_else_ce/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ConditionsSelect/MenuList/utils/constants';
|
||||
import { getCheckboxState } from '../../../utils';
|
||||
import createCollapsesObject from './utils/createCollapsesObject';
|
||||
import SubUl from './SubUl';
|
||||
import Ul from './Ul';
|
||||
import UpperFirst from './UpperFirst';
|
||||
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
|
||||
const MenuList = ({ selectProps, ...rest }) => {
|
||||
const Component = components.MenuList;
|
||||
const { arrayOfOptionsGroupedByCategory } = selectProps;
|
||||
|
||||
const initCollapses = useMemo(() => createCollapsesObject(arrayOfOptionsGroupedByCategory), [
|
||||
arrayOfOptionsGroupedByCategory,
|
||||
]);
|
||||
const [collapses, setCollapses] = useState(initCollapses);
|
||||
|
||||
const toggleCollapse = collapseName => {
|
||||
setCollapses(prevState => ({ ...prevState, [collapseName]: !collapses[collapseName] }));
|
||||
};
|
||||
|
||||
return (
|
||||
<Component {...rest}>
|
||||
<Ul disabled={IS_DISABLED}>
|
||||
{arrayOfOptionsGroupedByCategory.map((category, index) => {
|
||||
const [categoryName, conditions] = category;
|
||||
const checkboxName = `${selectProps.name}..${categoryName}`;
|
||||
|
||||
const {
|
||||
hasAllActionsSelected: hasAllConditionsSelected,
|
||||
hasSomeActionsSelected: hasSomeConditionsSelected,
|
||||
} = getCheckboxState(selectProps.value);
|
||||
|
||||
return (
|
||||
<li key={categoryName}>
|
||||
<div>
|
||||
<Flex justifyContent="space-between">
|
||||
<Label
|
||||
htmlFor="overrideReactSelectBehavior"
|
||||
onClick={() => {
|
||||
if (!IS_DISABLED) {
|
||||
selectProps.onCategoryChange({
|
||||
keys: [selectProps.name, categoryName],
|
||||
value: !hasAllConditionsSelected,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Checkbox
|
||||
disabled={IS_DISABLED}
|
||||
id="checkCategory"
|
||||
name={checkboxName}
|
||||
onChange={() => {}}
|
||||
someChecked={hasSomeConditionsSelected}
|
||||
value={hasAllConditionsSelected}
|
||||
/>
|
||||
<UpperFirst content={categoryName} />
|
||||
</Flex>
|
||||
</Label>
|
||||
<div
|
||||
style={{ flex: 1, textAlign: 'end', cursor: 'pointer' }}
|
||||
onClick={() => toggleCollapse(categoryName)}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
style={{
|
||||
margin: 'auto',
|
||||
fontSize: '11px',
|
||||
color: '#919bae',
|
||||
}}
|
||||
icon={collapses[categoryName] ? 'chevron-up' : 'chevron-down'}
|
||||
/>
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
<SubUl tag="ul" isOpen={collapses[categoryName]}>
|
||||
{conditions.map(condition => {
|
||||
const checkboxValue = get(selectProps.value, [categoryName, condition.id], false);
|
||||
|
||||
return (
|
||||
<li key={condition.id}>
|
||||
<Flex>
|
||||
<Label
|
||||
htmlFor={condition.id}
|
||||
message={condition.displayName}
|
||||
onClick={() => {
|
||||
if (!IS_DISABLED) {
|
||||
selectProps.onChange({
|
||||
keys: [selectProps.name, categoryName, condition.id],
|
||||
value: !checkboxValue,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Checkbox
|
||||
id="check"
|
||||
name={condition.id}
|
||||
// Remove the handler
|
||||
onChange={() => {}}
|
||||
value={checkboxValue}
|
||||
/>
|
||||
{condition.displayName}
|
||||
</Flex>
|
||||
</Label>
|
||||
</Flex>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</SubUl>
|
||||
{index + 1 < arrayOfOptionsGroupedByCategory.length.length && (
|
||||
<div style={{ paddingTop: '17px' }} />
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</Ul>
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
MenuList.propTypes = {
|
||||
selectProps: PropTypes.shape({
|
||||
arrayOfOptionsGroupedByCategory: PropTypes.array.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onCategoryChange: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.object.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
export default MenuList;
|
@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Creates an object with keys corresponding to the categoryName and leafs to false except for the first category
|
||||
*
|
||||
* @param {array<array>} arrayOfCategories
|
||||
* @returns {object}
|
||||
*/
|
||||
const createCollapsesObject = arrayOfCategories =>
|
||||
arrayOfCategories.reduce((acc, current, index) => {
|
||||
acc[current[0]] = index === 0;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export default createCollapsesObject;
|
@ -1,13 +0,0 @@
|
||||
import createCollapsesObject from '../createCollapsesObject';
|
||||
|
||||
describe('ADMIN | COMPONENTS | ROLES | ConditionsSelect | utils | createCollapsesObject', () => {
|
||||
it('should return an object of collapses', () => {
|
||||
const arrayOfCategories = [['default', [{ id: 'test' }]], ['custom', { id: 'test' }]];
|
||||
const expected = {
|
||||
default: true,
|
||||
custom: false,
|
||||
};
|
||||
|
||||
expect(createCollapsesObject(arrayOfCategories)).toEqual(expected);
|
||||
});
|
||||
});
|
@ -1,46 +0,0 @@
|
||||
/* eslint-disable indent */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { components } from 'react-select';
|
||||
import { Text } from '@buffetjs/core';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { createArrayOfValues } from '../../utils';
|
||||
|
||||
const Value = ({ children, selectProps, ...props }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const SingleValue = components.SingleValue;
|
||||
const valuesArray = createArrayOfValues(selectProps.value).filter(val => val);
|
||||
|
||||
return (
|
||||
<SingleValue {...props}>
|
||||
<Text style={{ paddingTop: 1 }}>
|
||||
{valuesArray.length === 0
|
||||
? formatMessage({ id: 'Settings.permissions.conditions.none-selected' })
|
||||
: formatMessage(
|
||||
{
|
||||
id: `Settings.permissions.conditions.selected.${
|
||||
selectProps.value.length > 1 ? 'plural' : 'singular'
|
||||
}`,
|
||||
},
|
||||
{ number: valuesArray.length }
|
||||
)}
|
||||
</Text>
|
||||
</SingleValue>
|
||||
);
|
||||
};
|
||||
|
||||
Value.defaultProps = {
|
||||
children: null,
|
||||
selectProps: {
|
||||
value: [],
|
||||
},
|
||||
};
|
||||
|
||||
Value.propTypes = {
|
||||
children: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
|
||||
selectProps: PropTypes.shape({
|
||||
value: PropTypes.object,
|
||||
}),
|
||||
};
|
||||
|
||||
export default Value;
|
@ -1,67 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import Select from 'react-select';
|
||||
import { useIntl } from 'react-intl';
|
||||
import MenuList from './MenuList';
|
||||
import ClearIndicator from './ClearIndicator';
|
||||
import DropdownIndicator from './CustomDropdownIndicator';
|
||||
import IndicatorSeparator from './IndicatorSeparator';
|
||||
import SingleValue from './SingleValue';
|
||||
import selectStyle from '../utils/selectStyle';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding-left: ${({ theme }) => theme.main.sizes.paddings.md};
|
||||
width: 60%;
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'default')};
|
||||
`;
|
||||
|
||||
const ConditionsSelect = ({
|
||||
arrayOfOptionsGroupedByCategory,
|
||||
isFormDisabled,
|
||||
name,
|
||||
onCategoryChange,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Wrapper disabled={isFormDisabled}>
|
||||
<Select
|
||||
components={{
|
||||
ClearIndicator,
|
||||
DropdownIndicator,
|
||||
IndicatorSeparator,
|
||||
SingleValue,
|
||||
MenuList,
|
||||
}}
|
||||
arrayOfOptionsGroupedByCategory={arrayOfOptionsGroupedByCategory}
|
||||
isDisabled={isFormDisabled}
|
||||
name={name}
|
||||
onChange={onChange}
|
||||
isClearable={false}
|
||||
isLoading={false}
|
||||
closeMenuOnSelect={false}
|
||||
isSearchable={false}
|
||||
hideSelectedOptions={false}
|
||||
placeholder={formatMessage({ id: 'Settings.permissions.conditions.anytime' })}
|
||||
onCategoryChange={onCategoryChange}
|
||||
options={[]}
|
||||
styles={selectStyle}
|
||||
value={value}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
ConditionsSelect.propTypes = {
|
||||
arrayOfOptionsGroupedByCategory: PropTypes.array.isRequired,
|
||||
isFormDisabled: PropTypes.bool.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onCategoryChange: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ConditionsSelect;
|
@ -1,95 +0,0 @@
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
|
||||
const selectStyle = {
|
||||
container: base => ({
|
||||
...base,
|
||||
width: '70%',
|
||||
alignItems: 'center',
|
||||
height: '36px',
|
||||
}),
|
||||
menu: base => ({
|
||||
...base,
|
||||
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,
|
||||
paddingBottom: 9,
|
||||
paddingTop: 10,
|
||||
}),
|
||||
multiValue: base => ({
|
||||
...base,
|
||||
backgroundColor: 'none',
|
||||
color: '#333740',
|
||||
}),
|
||||
multiValueLabel: base => ({
|
||||
...base,
|
||||
fontSize: '13px',
|
||||
}),
|
||||
multiValueRemove: base => ({
|
||||
...base,
|
||||
display: 'none',
|
||||
}),
|
||||
|
||||
control: (base, state) => {
|
||||
const borderRadiusStyle = state.selectProps.menuIsOpen
|
||||
? {
|
||||
borderBottomLeftRadius: '0 !important',
|
||||
borderBottomRightRadius: '0 !important',
|
||||
}
|
||||
: {};
|
||||
|
||||
const {
|
||||
selectProps: { error, value },
|
||||
} = state;
|
||||
|
||||
let border;
|
||||
let borderBottom;
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
return {
|
||||
...base,
|
||||
fontSize: 13,
|
||||
minHeight: 34,
|
||||
top: '1px',
|
||||
border,
|
||||
outline: 0,
|
||||
boxShadow: 0,
|
||||
borderRadius: '2px !important',
|
||||
...borderRadiusStyle,
|
||||
borderBottom,
|
||||
};
|
||||
},
|
||||
valueContainer: base => ({
|
||||
...base,
|
||||
padding: '2px 4px 4px 10px',
|
||||
lineHeight: '18px',
|
||||
minWidth: 200,
|
||||
}),
|
||||
placeholder: base => ({
|
||||
...base,
|
||||
paddingTop: 1,
|
||||
color: 'black',
|
||||
}),
|
||||
};
|
||||
|
||||
export default selectStyle;
|
@ -770,6 +770,10 @@ describe('Admin | containers | RoleCreatePage', () => {
|
||||
background: #d9d8ff;
|
||||
}
|
||||
|
||||
.c40:hover:not([aria-disabled='true']) svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
.c47 {
|
||||
background: transparent;
|
||||
border: none;
|
||||
@ -857,10 +861,6 @@ describe('Admin | containers | RoleCreatePage', () => {
|
||||
height: 5.5rem;
|
||||
}
|
||||
|
||||
.c44:hover svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
@media (max-width:68.75rem) {
|
||||
.c20 {
|
||||
grid-column: span;
|
||||
|
@ -853,6 +853,10 @@ describe('Admin | containers | RoleEditPage', () => {
|
||||
background: #d9d8ff;
|
||||
}
|
||||
|
||||
.c47:hover:not([aria-disabled='true']) svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
.c54 {
|
||||
background: transparent;
|
||||
border: none;
|
||||
@ -940,10 +944,6 @@ describe('Admin | containers | RoleEditPage', () => {
|
||||
height: 5.5rem;
|
||||
}
|
||||
|
||||
.c51:hover svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
@media (max-width:68.75rem) {
|
||||
.c27 {
|
||||
grid-column: span;
|
||||
|
Loading…
x
Reference in New Issue
Block a user