mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 17:00:55 +00:00
Created conditions modal
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
5a53675b8f
commit
95eeed0dec
@ -0,0 +1,11 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
height: 36px;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 18px;
|
||||
background-color: ${({ theme, isGrey }) => (isGrey ? '#fafafb' : theme.main.colors.white)};
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text, Padded, Flex } from '@buffetjs/core';
|
||||
import { useIntl } from 'react-intl';
|
||||
// import { usePermissionsDataManager } from '../contexts/PermissionsDataManagerContext';
|
||||
|
||||
import ConditionsSelect from '../ConditionsSelect';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const ActionRow = ({
|
||||
arrayOfOptionsGroupedByCategory,
|
||||
isGrey,
|
||||
label,
|
||||
name,
|
||||
onCategoryChange,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Wrapper isGrey={isGrey}>
|
||||
<Padded style={{ width: 200 }} top left right bottom size="sm">
|
||||
<Flex>
|
||||
<Text
|
||||
lineHeight="19px"
|
||||
color="grey"
|
||||
fontSize="xs"
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{formatMessage({
|
||||
id: 'Settings.permissions.conditions.can',
|
||||
})}
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
title={label}
|
||||
lineHeight="19px"
|
||||
fontWeight="bold"
|
||||
fontSize="xs"
|
||||
textTransform="uppercase"
|
||||
color="mediumBlue"
|
||||
style={{ maxWidth: '60%' }}
|
||||
ellipsis
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
<Text
|
||||
lineHeight="19px"
|
||||
color="grey"
|
||||
fontSize="xs"
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
|
||||
{formatMessage({
|
||||
id: 'Settings.permissions.conditions.when',
|
||||
})}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Padded>
|
||||
<ConditionsSelect
|
||||
arrayOfOptionsGroupedByCategory={arrayOfOptionsGroupedByCategory}
|
||||
name={name}
|
||||
onCategoryChange={onCategoryChange}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
ActionRow.propTypes = {
|
||||
arrayOfOptionsGroupedByCategory: PropTypes.array.isRequired,
|
||||
isGrey: PropTypes.bool.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.object.isRequired,
|
||||
onCategoryChange: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
export default ActionRow;
|
@ -0,0 +1,15 @@
|
||||
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;
|
@ -0,0 +1,39 @@
|
||||
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;
|
@ -0,0 +1,3 @@
|
||||
const IndicatorSeparator = () => null;
|
||||
|
||||
export default IndicatorSeparator;
|
@ -0,0 +1,48 @@
|
||||
/* 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;
|
@ -0,0 +1,80 @@
|
||||
/* 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: #007eff;
|
||||
font-weight: 700;
|
||||
z-index: 100;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: -30px;
|
||||
right: -30px;
|
||||
bottom: 0;
|
||||
background-color: #e6f0fb;
|
||||
}
|
||||
}
|
||||
}
|
||||
${({ 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;
|
@ -0,0 +1,6 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import { upperFirst } from 'lodash';
|
||||
|
||||
const UpperFirst = ({ content }) => upperFirst(content);
|
||||
|
||||
export default UpperFirst;
|
@ -0,0 +1,139 @@
|
||||
/* 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 SubUl from './SubUl';
|
||||
import Ul from './Ul';
|
||||
import UpperFirst from './UpperFirst';
|
||||
import { getCheckboxState } from '../../../utils';
|
||||
import createCollapsesObject from './utils/createCollapsesObject';
|
||||
|
||||
/* 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
|
||||
// TODO
|
||||
disabled={false}
|
||||
>
|
||||
{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={() =>
|
||||
selectProps.onCategoryChange({
|
||||
keys: [selectProps.name, categoryName],
|
||||
value: !hasAllConditionsSelected,
|
||||
})}
|
||||
>
|
||||
<Flex>
|
||||
<Checkbox
|
||||
// TODO
|
||||
disabled={false}
|
||||
id="checkCategory"
|
||||
// TODO
|
||||
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={() => {
|
||||
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;
|
@ -0,0 +1,8 @@
|
||||
const createCollapsesObject = arrayOfCategories =>
|
||||
arrayOfCategories.reduce((acc, current, index) => {
|
||||
acc[current[0]] = index === 0;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export default createCollapsesObject;
|
@ -0,0 +1,46 @@
|
||||
/* 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
|
||||
? 'Anytime'
|
||||
: 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;
|
@ -0,0 +1,11 @@
|
||||
import styled from 'styled-components';
|
||||
import { Option } from '@buffetjs/core';
|
||||
|
||||
const StyledOption = styled(Option)`
|
||||
> span {
|
||||
display: block !important;
|
||||
color: #007eff !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledOption;
|
@ -0,0 +1,69 @@
|
||||
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: 30px;
|
||||
width: 60%;
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'default')};
|
||||
`;
|
||||
|
||||
const ConditionsSelect = ({
|
||||
arrayOfOptionsGroupedByCategory,
|
||||
name,
|
||||
onCategoryChange,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
// TODO
|
||||
disabled={false}
|
||||
>
|
||||
<Select
|
||||
components={{
|
||||
ClearIndicator,
|
||||
DropdownIndicator,
|
||||
IndicatorSeparator,
|
||||
SingleValue,
|
||||
MenuList,
|
||||
}}
|
||||
arrayOfOptionsGroupedByCategory={arrayOfOptionsGroupedByCategory}
|
||||
// TODO
|
||||
isDisabled={false}
|
||||
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,
|
||||
name: PropTypes.string.isRequired,
|
||||
onCategoryChange: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ConditionsSelect;
|
@ -1,12 +1,59 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { cloneDeep, get, groupBy, set } from 'lodash';
|
||||
import { Modal, ModalHeader, ModalFooter } from 'strapi-helper-plugin';
|
||||
import { Button, Text, Padded } from '@buffetjs/core';
|
||||
import { useIntl } from 'react-intl';
|
||||
import createDefaultConditionsForm from './utils/createDefaultConditionsForm';
|
||||
import ActionRow from './ActionRow';
|
||||
import Separator from './Separator';
|
||||
import { usePermissionsDataManager } from '../contexts/PermissionsDataManagerContext';
|
||||
import updateValues from '../Permissions/utils/updateValues';
|
||||
|
||||
const ConditionsModal = ({ headerBreadCrumbs, isOpen, onClosed, onToggle }) => {
|
||||
const ConditionsModal = ({ actions, headerBreadCrumbs, isOpen, onClosed, onToggle }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { availableConditions, modifiedData } = usePermissionsDataManager();
|
||||
|
||||
const arrayOfOptionsGroupedByCategory = useMemo(() => {
|
||||
return Object.entries(groupBy(availableConditions, 'category'));
|
||||
}, [availableConditions]);
|
||||
|
||||
const actionsToDisplay = actions.filter(
|
||||
({ isDisplayed, hasSomeActionsSelected, hasAllActionsSelected }) =>
|
||||
isDisplayed && (hasSomeActionsSelected || hasAllActionsSelected)
|
||||
);
|
||||
|
||||
const initState = useMemo(() => {
|
||||
return createDefaultConditionsForm(
|
||||
actionsToDisplay,
|
||||
modifiedData,
|
||||
arrayOfOptionsGroupedByCategory
|
||||
);
|
||||
}, [actionsToDisplay, modifiedData, arrayOfOptionsGroupedByCategory]);
|
||||
|
||||
const [state, setState] = useState(initState);
|
||||
|
||||
const handleCategoryChange = ({ keys, value }) => {
|
||||
setState(prevState => {
|
||||
const updatedState = cloneDeep(prevState);
|
||||
const objToUpdate = get(prevState, keys, {});
|
||||
const updatedValues = updateValues(objToUpdate, value);
|
||||
|
||||
set(updatedState, keys, updatedValues);
|
||||
|
||||
return updatedState;
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = ({ keys, value }) => {
|
||||
setState(prevState => {
|
||||
const updatedState = cloneDeep(prevState);
|
||||
|
||||
set(updatedState, keys, value);
|
||||
|
||||
return updatedState;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal withoverflow="true" onClosed={onClosed} isOpen={isOpen} onToggle={onToggle}>
|
||||
@ -18,20 +65,27 @@ const ConditionsModal = ({ headerBreadCrumbs, isOpen, onClosed, onToggle }) => {
|
||||
})}
|
||||
</Text>
|
||||
<Separator />
|
||||
{/* {actions.length === 0 && (
|
||||
{actionsToDisplay.length === 0 && (
|
||||
<Text fontSize="md" color="grey">
|
||||
{formatMessage({ id: 'Settings.permissions.conditions.no-actions' })}
|
||||
</Text>
|
||||
)}
|
||||
{actions.map((action, index) => (
|
||||
<ActionRow
|
||||
key={action.id}
|
||||
action={action}
|
||||
isGrey={index % 2 === 0}
|
||||
value={conditions[action.id]}
|
||||
onChange={val => handleSelectChange(action.id, val)}
|
||||
/>
|
||||
))} */}
|
||||
{actionsToDisplay.map(({ actionId, label, pathToConditionsObject }, index) => {
|
||||
const name = pathToConditionsObject.join('..');
|
||||
|
||||
return (
|
||||
<ActionRow
|
||||
key={actionId}
|
||||
arrayOfOptionsGroupedByCategory={arrayOfOptionsGroupedByCategory}
|
||||
label={label}
|
||||
isGrey={index % 2 === 0}
|
||||
name={name}
|
||||
onCategoryChange={handleCategoryChange}
|
||||
onChange={handleChange}
|
||||
value={get(state, name, {})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Padded>
|
||||
<ModalFooter>
|
||||
<section>
|
||||
@ -51,6 +105,16 @@ const ConditionsModal = ({ headerBreadCrumbs, isOpen, onClosed, onToggle }) => {
|
||||
};
|
||||
|
||||
ConditionsModal.propTypes = {
|
||||
actions: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
actionId: PropTypes.string.isRequired,
|
||||
checkboxName: PropTypes.string,
|
||||
hasSomeActionsSelected: PropTypes.bool.isRequired,
|
||||
hasAllActionsSelected: PropTypes.bool,
|
||||
isDisplayed: PropTypes.bool.isRequired,
|
||||
label: PropTypes.string,
|
||||
})
|
||||
).isRequired,
|
||||
headerBreadCrumbs: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClosed: PropTypes.func.isRequired,
|
||||
|
@ -0,0 +1,46 @@
|
||||
import { get } from 'lodash';
|
||||
|
||||
const createConditionsForm = (conditions, valueObject) => {
|
||||
return conditions.reduce((acc, current) => {
|
||||
acc[current.id] = get(valueObject, current.id, true);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
const createCategoryForm = (arrayOfOptions, valueObject) => {
|
||||
return arrayOfOptions.reduce((acc, current) => {
|
||||
const [categoryName, relatedConditions] = current;
|
||||
|
||||
const conditionsForm = createConditionsForm(relatedConditions, valueObject);
|
||||
|
||||
acc[categoryName] = conditionsForm;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
const createDefaultConditionsForm = (
|
||||
actionsToDisplay,
|
||||
modifiedData,
|
||||
arrayOfOptionsGroupedByCategory
|
||||
) => {
|
||||
return actionsToDisplay.reduce((acc, current) => {
|
||||
const valueFromModifiedData = get(
|
||||
modifiedData,
|
||||
[...current.pathToConditionsObject, 'conditions'],
|
||||
{}
|
||||
);
|
||||
|
||||
const categoryDefaultForm = createCategoryForm(
|
||||
arrayOfOptionsGroupedByCategory,
|
||||
valueFromModifiedData
|
||||
);
|
||||
|
||||
acc[current.pathToConditionsObject.join('..')] = categoryDefaultForm;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export default createDefaultConditionsForm;
|
@ -0,0 +1,95 @@
|
||||
/* 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;
|
@ -108,6 +108,7 @@ const Collapse = ({ availableActions, isActive, isGrey, label, onClickToggle, pa
|
||||
{modalState.isMounted && (
|
||||
<ConditionsModal
|
||||
headerBreadCrumbs={[label, 'app.components.LeftMenuLinkContainer.settings']}
|
||||
actions={checkboxesActions}
|
||||
isOpen={modalState.isOpen}
|
||||
onClosed={handleModalClose}
|
||||
onToggle={handleToggleModalIsOpen}
|
||||
|
@ -2,7 +2,7 @@ import { get, isEmpty } from 'lodash';
|
||||
import { createArrayOfValues, getCheckboxState } from '../../../utils';
|
||||
|
||||
const generateCheckboxesActions = (availableActions, modifiedData, pathToData) => {
|
||||
return availableActions.map(({ actionId, isDisplayed, applyToProperties }) => {
|
||||
return availableActions.map(({ actionId, isDisplayed, applyToProperties, label }) => {
|
||||
if (!isDisplayed) {
|
||||
return { actionId, hasSomeActionsSelected: false, isDisplayed };
|
||||
}
|
||||
@ -29,6 +29,8 @@ const generateCheckboxesActions = (availableActions, modifiedData, pathToData) =
|
||||
hasSomeActionsSelected: value,
|
||||
isDisplayed,
|
||||
isParentCheckbox: false,
|
||||
label,
|
||||
pathToConditionsObject: baseCheckboxNameArray,
|
||||
};
|
||||
}
|
||||
|
||||
@ -44,6 +46,8 @@ const generateCheckboxesActions = (availableActions, modifiedData, pathToData) =
|
||||
hasSomeActionsSelected,
|
||||
isDisplayed,
|
||||
isParentCheckbox: true,
|
||||
label,
|
||||
pathToConditionsObject: baseCheckboxNameArray,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -68,6 +68,7 @@ const Permissions = forwardRef(({ layout }, ref) => {
|
||||
return (
|
||||
<PermissionsDataManagerProvider
|
||||
value={{
|
||||
availableConditions: layout.conditions,
|
||||
modifiedData,
|
||||
onChangeSimpleCheckbox: handleChangeSimpleCheckbox,
|
||||
onChangeParentCheckbox: handleChangeParentCheckbox,
|
||||
|
@ -16,6 +16,7 @@ const usePermissionsDataManager = () => useContext(PermissionsDataManagerContext
|
||||
PermissionsDataManagerProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
value: PropTypes.exact({
|
||||
availableConditions: PropTypes.array.isRequired,
|
||||
modifiedData: PropTypes.object.isRequired,
|
||||
onChangeCollectionTypeLeftActionRowCheckbox: PropTypes.func.isRequired,
|
||||
onChangeSimpleCheckbox: PropTypes.func.isRequired,
|
||||
|
@ -424,6 +424,7 @@ const data = {
|
||||
label: 'Publish',
|
||||
actionId: 'content-manager.explorer.publish',
|
||||
subjects: ['restaurant'],
|
||||
applyToProperties: ['locales'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user