Merge branch 'migrations/admin-users-filters' of github.com:strapi/strapi into migrations/admin-users-delete

This commit is contained in:
soupette 2021-09-02 13:20:57 +02:00
commit 99ba54cb43
12 changed files with 123 additions and 91 deletions

View File

@ -59,6 +59,7 @@ module.exports = {
'<rootDir>/test/config/front/test-bundler.js',
'<rootDir>/packages/admin-test-utils/lib/mocks/LocalStorageMock.js',
'<rootDir>/packages/admin-test-utils/lib/mocks/IntersectionObserver.js',
'<rootDir>/packages/admin-test-utils/lib/mocks/ResizeObserver.js',
],
testPathIgnorePatterns: [
'/node_modules/',

View File

@ -0,0 +1,11 @@
'use strict';
class ResizeObserverMock {
constructor() {
this.disconnect = () => null;
this.observe = () => null;
this.unobserve = () => null;
}
}
global.ResizeObserver = ResizeObserverMock;

View File

@ -1,10 +1,10 @@
import React from 'react';
import { Box, Row, TableLabel } from '@strapi/parts';
import { MultiSelectNested } from '@strapi/parts/Select';
import { upperFirst } from 'lodash';
import PropTypes from 'prop-types';
import { Row, TableLabel } from '@strapi/parts';
import React from 'react';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
// import ConditionsSelect from '../ConditionsSelect';
import { rowHeight } from '../../Permissions/utils/constants';
const RowWrapper = styled(Row)`
@ -12,16 +12,46 @@ const RowWrapper = styled(Row)`
`;
const ActionRow = ({
// arrayOfOptionsGroupedByCategory,
// isFormDisabled,
arrayOfOptionsGroupedByCategory,
isFormDisabled,
isGrey,
label,
// name,
// onCategoryChange,
// onChange,
// value,
name,
onChange,
value,
}) => {
const { formatMessage } = useIntl();
const options = arrayOfOptionsGroupedByCategory.reduce((arr, curr) => {
const [label, children] = curr;
const obj = {
label: upperFirst(label),
children: children.map(child => ({
label: child.displayName,
value: child.id,
})),
};
return [...arr, obj];
}, []);
// Output: ['value1', 'value2']
const values = Object.values(value)
.map(x =>
Object.entries(x)
.filter(([, value]) => value)
.map(([key]) => key)
)
.flat();
// ! Only expects arrayOfOpt to be [['default', obj]] - might break in future changes
const handleChange = val => {
const [[, values]] = arrayOfOptionsGroupedByCategory;
const formattedValues = values.reduce(
(acc, curr) => ({ [curr.id]: val.includes(curr.id), ...acc }),
{}
);
onChange(name, formattedValues);
};
return (
<RowWrapper as="li" background={isGrey ? 'neutral100' : 'neutral0'}>
@ -56,26 +86,27 @@ const ActionRow = ({
})}
</TableLabel>
</Row>
{/* <ConditionsSelect
arrayOfOptionsGroupedByCategory={arrayOfOptionsGroupedByCategory}
name={name}
isFormDisabled={isFormDisabled}
onCategoryChange={onCategoryChange}
onChange={onChange}
value={value}
/> */}
<Box style={{ maxWidth: 430, width: '100%' }}>
<MultiSelectNested
id={name}
customizeContent={values => `${values.length} currently selected`}
onChange={handleChange}
value={values}
options={options}
disabled={isFormDisabled}
/>
</Box>
</RowWrapper>
);
};
ActionRow.propTypes = {
// arrayOfOptionsGroupedByCategory: PropTypes.array.isRequired,
// isFormDisabled: PropTypes.bool.isRequired,
arrayOfOptionsGroupedByCategory: PropTypes.array.isRequired,
isFormDisabled: PropTypes.bool.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,
name: PropTypes.string.isRequired,
value: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
};
export default ActionRow;

View File

@ -3,31 +3,24 @@ import {
Breadcrumbs,
Button,
Crumb,
Divider,
H2,
ModalFooter,
ModalHeader,
ModalLayout,
Stack,
Text,
Divider,
} from '@strapi/parts';
import { cloneDeep, get, groupBy, set, upperFirst } from 'lodash';
import produce from 'immer';
import { get, groupBy, upperFirst } from 'lodash';
import PropTypes from 'prop-types';
import React, { useMemo, useState } from 'react';
import { useIntl } from 'react-intl';
import { usePermissionsDataManager } from '../../../hooks';
import updateValues from '../Permissions/utils/updateValues';
import ActionRow from './ActionRow';
import createDefaultConditionsForm from './utils/createDefaultConditionsForm';
const ConditionsModal = ({
actions,
headerBreadCrumbs,
isOpen,
isFormDisabled,
onClosed,
onToggle,
}) => {
const ConditionsModal = ({ actions, headerBreadCrumbs, isFormDisabled, onClosed, onToggle }) => {
const { formatMessage } = useIntl();
const { availableConditions, modifiedData, onChangeConditions } = usePermissionsDataManager();
@ -50,26 +43,20 @@ const ConditionsModal = ({
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);
const handleChange = (name, values) => {
setState(
produce(draft => {
if (!draft[name]) {
draft[name] = {};
}
set(updatedState, keys, updatedValues);
if (!draft[name].default) {
draft[name].default = {};
}
return updatedState;
});
};
const handleChange = ({ keys, value }) => {
setState(prevState => {
const updatedState = cloneDeep(prevState);
set(updatedState, keys, value);
return updatedState;
});
draft[name].default = values;
})
);
};
const handleSubmit = () => {
@ -89,8 +76,6 @@ const ConditionsModal = ({
onToggle();
};
if (!isOpen) return null;
return (
<ModalLayout onClose={onClosed}>
<ModalHeader>
@ -140,7 +125,6 @@ const ConditionsModal = ({
isFormDisabled={isFormDisabled}
isGrey={index % 2 === 0}
name={name}
onCategoryChange={handleCategoryChange}
onChange={handleChange}
value={get(state, name, {})}
/>
@ -181,7 +165,6 @@ ConditionsModal.propTypes = {
})
).isRequired,
headerBreadCrumbs: PropTypes.arrayOf(PropTypes.string).isRequired,
isOpen: PropTypes.bool.isRequired,
isFormDisabled: PropTypes.bool.isRequired,
onClosed: PropTypes.func.isRequired,
onToggle: PropTypes.func.isRequired,

View File

@ -228,14 +228,15 @@ const Collapse = ({
)}
</Row>
<Box style={{ width: 120 }} />
<ConditionsModal
headerBreadCrumbs={[label, 'app.components.LeftMenuLinkContainer.settings']}
actions={checkboxesActions}
isOpen={isModalOpen}
isFormDisabled={isFormDisabled}
onClosed={handleModalClose}
onToggle={handleToggleModalIsOpen}
/>
{isModalOpen && (
<ConditionsModal
headerBreadCrumbs={[label, 'app.components.LeftMenuLinkContainer.settings']}
actions={checkboxesActions}
isFormDisabled={isFormDisabled}
onClosed={handleModalClose}
onToggle={handleToggleModalIsOpen}
/>
)}
</Wrapper>
<AbsoluteBox>
<ConditionsButton

View File

@ -130,14 +130,15 @@ const SubCategory = ({ categoryName, isFormDisabled, subCategoryName, actions, p
/>
</Row>
</Box>
<ConditionsModal
headerBreadCrumbs={[categoryName, subCategoryName]}
actions={formattedActions}
isOpen={isModalOpen}
isFormDisabled={isFormDisabled}
onClosed={handleModalClose}
onToggle={handleToggleModalIsOpen}
/>
{isModalOpen && (
<ConditionsModal
headerBreadCrumbs={[categoryName, subCategoryName]}
actions={formattedActions}
isFormDisabled={isFormDisabled}
onClosed={handleModalClose}
onToggle={handleToggleModalIsOpen}
/>
)}
</>
);
};

View File

@ -1,16 +1,16 @@
import { useEffect, useReducer } from 'react';
import { hasPermissions, useRBACProvider, useStrapiApp } from '@strapi/helper-plugin';
import { hasPermissions, useRBACProvider, useStrapiApp, useAppInfos } from '@strapi/helper-plugin';
import reducer, { initialState } from './reducer';
import init from './init';
const useSettingsMenu = (noCheck = false) => {
const { allPermissions: permissions } = useRBACProvider();
const { shouldUpdateStrapi } = useAppInfos();
const { settings } = useStrapiApp();
const [{ isLoading, menu }, dispatch] = useReducer(reducer, initialState, () =>
init(initialState, settings)
init(initialState, { settings, shouldUpdateStrapi })
);
useEffect(() => {

View File

@ -4,11 +4,15 @@ import adminPermissions from '../../permissions';
import formatLinks from './utils/formatLinks';
import globalLinks from './utils/globalLinks';
const init = (initialState, settings) => {
const init = (initialState, { settings, shouldUpdateStrapi }) => {
// Retrieve the links that will be injected into the global section
const pluginsGlobalLinks = settings.global.links;
// Sort the links by name
const sortedGlobalLinks = sortLinks([...pluginsGlobalLinks, ...globalLinks]);
const sortedGlobalLinks = sortLinks([...pluginsGlobalLinks, ...globalLinks]).map(link => ({
...link,
hasNotification: link.id === 'application-infos' && shouldUpdateStrapi,
}));
const otherSections = Object.values(omit(settings, 'global'));
const menu = [

View File

@ -38,7 +38,7 @@ const SettingsNav = ({ menu }) => {
{sections.map(section => (
<SubNavSection key={section.id} label={formatMessage(section.intlLabel)}>
{section.links.map(link => (
<SubNavLink to={link.to} key={link.id}>
<SubNavLink withBullet={link.hasNotification} to={link.to} key={link.id}>
{formatMessage(link.intlLabel)}
</SubNavLink>
))}

View File

@ -40,8 +40,8 @@
"@fortawesome/react-fontawesome": "^0.1.14",
"@strapi/babel-plugin-switch-ee-ce": "1.0.0",
"@strapi/helper-plugin": "3.6.7",
"@strapi/icons": "0.0.1-alpha.18",
"@strapi/parts": "0.0.1-alpha.18",
"@strapi/icons": "0.0.1-alpha.19",
"@strapi/parts": "0.0.1-alpha.19",
"@strapi/utils": "3.6.7",
"axios": "^0.21.1",
"babel-loader": "8.2.2",

View File

@ -53,8 +53,8 @@
"@storybook/builder-webpack5": "^6.3.7",
"@storybook/manager-webpack5": "^6.3.7",
"@storybook/react": "^6.3.7",
"@strapi/icons": "0.0.1-alpha.18",
"@strapi/parts": "0.0.1-alpha.18",
"@strapi/icons": "0.0.1-alpha.19",
"@strapi/parts": "0.0.1-alpha.19",
"babel-loader": "^8.2.2",
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.15.6",

View File

@ -4915,15 +4915,15 @@
resolve-from "^5.0.0"
store2 "^2.12.0"
"@strapi/icons@0.0.1-alpha.18":
version "0.0.1-alpha.18"
resolved "https://registry.yarnpkg.com/@strapi/icons/-/icons-0.0.1-alpha.18.tgz#c64ca4a896b965b1ea02b2863352391daa5406ff"
integrity sha512-QDjCckoI5vGQc6eH/rgFxLMGrBkYqmbNsMAb7T5GOUhJxoSymPM4VPKOjqL36u6MRpi1xqYdw3GBiv48tnxZVw==
"@strapi/icons@0.0.1-alpha.19":
version "0.0.1-alpha.19"
resolved "https://registry.yarnpkg.com/@strapi/icons/-/icons-0.0.1-alpha.19.tgz#88153c77ff02deccfedffb1dc2e7f0f4cc2f830a"
integrity sha512-nFpT3Gsp6nQ4+FNd9DkbqhMZrX9KJbWXLQ6XFHhtYdNVA3n5vr2/0MFaqWrvYwxpnxMs3gn1xZOjG4+VzLBwbA==
"@strapi/parts@0.0.1-alpha.18":
version "0.0.1-alpha.18"
resolved "https://registry.yarnpkg.com/@strapi/parts/-/parts-0.0.1-alpha.18.tgz#19306892ba98404f7554360760f1870a2e57e381"
integrity sha512-x0LcIounSdgFY7lVsOjinh6ksS9/Nw2/CHNDVW7ZZTuXS5QHODebNlZibrTyPVZNLSJniYqn8P0rxAtc+FcLjQ==
"@strapi/parts@0.0.1-alpha.19":
version "0.0.1-alpha.19"
resolved "https://registry.yarnpkg.com/@strapi/parts/-/parts-0.0.1-alpha.19.tgz#e4c64c1f63256ab21f4ad643f684738a283c0efc"
integrity sha512-NzhwmCJnMNlCcRHpXTxILm0rVH+qLl2JoaCxx7XoMRnq4JZHHBaLjEiyTZHYJXRTdro+YUcWeayssL9kqEX8cw==
dependencies:
"@internationalized/number" "^3.0.2"
compute-scroll-into-view "^1.0.17"