Add plugins and settings tabs

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2021-02-15 12:49:54 +01:00
parent b225028b0f
commit 7dbc795288
9 changed files with 139 additions and 74 deletions

View File

@ -1,11 +1,4 @@
import React, {
forwardRef,
memo,
useCallback,
useImperativeHandle,
useMemo,
useReducer,
} from 'react';
import React, { forwardRef, memo, useCallback, useImperativeHandle, useReducer } from 'react';
import PropTypes from 'prop-types';
import { Tabs } from '../../../../../../admin/src/components/Roles';
import { roleTabsLabel as TAB_LABELS } from '../../../../../../admin/src/utils';
@ -13,12 +6,13 @@ import { PermissionsDataManagerProvider } from '../contexts/PermissionsDataManag
import ContentTypes from '../ContentTypes';
import PluginsAndSettings from '../PluginsAndSettings';
import layout from '../temp/fakeData';
import formatLayoutForSettingsAndPlugins from './utils/formatLayoutForSettingsAndPlugins';
import init from './init';
import reducer, { initialState } from './reducer';
const Permissions = forwardRef(({ layout }, ref) => {
const [{ modifiedData }, dispatch] = useReducer(reducer, initialState, () => init(layout));
const [{ layouts, modifiedData }, dispatch] = useReducer(reducer, initialState, () =>
init(layout)
);
useImperativeHandle(ref, () => {
return {
@ -71,14 +65,6 @@ const Permissions = forwardRef(({ layout }, ref) => {
});
}, []);
const pluginsSectionLayout = useMemo(() => {
return formatLayoutForSettingsAndPlugins(layout.sections.plugins, 'plugin');
}, [layout.sections.plugins]);
const settingsSectionLayout = useMemo(() => {
return formatLayoutForSettingsAndPlugins(layout.sections.settings, 'category');
}, [layout.sections.settings]);
return (
<PermissionsDataManagerProvider
value={{
@ -90,10 +76,10 @@ const Permissions = forwardRef(({ layout }, ref) => {
}}
>
<Tabs tabsLabel={TAB_LABELS}>
<ContentTypes layout={layout.sections.collectionTypes} kind="collectionTypes" />
<ContentTypes layout={layout.sections.singleTypes} kind="singleTypes" />
<PluginsAndSettings layout={pluginsSectionLayout} kind="plugins" />
<PluginsAndSettings layout={settingsSectionLayout} kind="settings" />
<ContentTypes layout={layouts.collectionTypes} kind="collectionTypes" />
<ContentTypes layout={layouts.singleTypes} kind="singleTypes" />
<PluginsAndSettings layout={layouts.plugins} kind="plugins" />
<PluginsAndSettings layout={layouts.settings} kind="settings" />
</Tabs>
</PermissionsDataManagerProvider>
);

View File

@ -1,11 +1,33 @@
import createDefaultForm from './utils/createdDefaultForm';
import createDefaultCTFormFromLayout from './utils/createDefaultCTFormFromLayout';
import createDefaultPluginsFormFromLayout from './utils/createDefaultPluginsFormFromLayout';
import formatLayoutForSettingsAndPlugins from './utils/formatLayoutForSettingsAndPlugins';
const init = layout => {
const defaultForm = createDefaultForm(layout);
const {
conditions,
sections: { collectionTypes, singleTypes, plugins, settings },
} = layout;
const layouts = {
collectionTypes,
singleTypes,
plugins: formatLayoutForSettingsAndPlugins(plugins, 'plugin'),
settings: formatLayoutForSettingsAndPlugins(settings, 'category'),
};
const defaultForm = {
collectionTypes: createDefaultCTFormFromLayout(
collectionTypes,
collectionTypes.actions || [],
conditions
),
singleTypes: createDefaultCTFormFromLayout(singleTypes, singleTypes.actions || [], conditions),
plugins: createDefaultPluginsFormFromLayout(layouts.plugins, conditions),
settings: createDefaultPluginsFormFromLayout(layouts.settings, conditions),
};
return {
initialData: defaultForm,
modifiedData: defaultForm,
layouts,
};
};

View File

@ -5,6 +5,7 @@ import updateValues from './utils/updateValues';
const initialState = {
initialData: {},
modifiedData: {},
layouts: {},
};
/* eslint-disable consistent-return */

View File

@ -0,0 +1,31 @@
import { createDefaultConditionsForm } from './createDefaultCTFormFromLayout';
const createSubCategoryForm = (actions, conditions) => {
return actions.reduce((acc, current) => {
acc[current.action] = {
enabled: false,
conditions: createDefaultConditionsForm(conditions),
};
return acc;
}, {});
};
const createChildrenDefaultForm = (childrenForm, conditions) => {
return childrenForm.reduce((acc, current) => {
acc[current.subCategoryId] = createSubCategoryForm(current.actions, conditions);
return acc;
}, {});
};
const createDefaultPluginsFormFromLayout = (pluginsLayout, conditions) => {
return pluginsLayout.reduce((acc, { categoryId, childrenForm }) => {
const childrenDefaultForm = createChildrenDefaultForm(childrenForm, conditions);
acc[categoryId] = childrenDefaultForm;
return acc;
}, {});
};
export default createDefaultPluginsFormFromLayout;

View File

@ -1,14 +0,0 @@
import createDefaultCTFormFromLayout from './createDefaultCTFormFromLayout';
const createDefaultForm = ({ conditions, sections: { collectionTypes, singleTypes } }) => {
return {
collectionTypes: createDefaultCTFormFromLayout(
collectionTypes,
collectionTypes.actions || [],
conditions
),
singleTypes: createDefaultCTFormFromLayout(singleTypes, singleTypes.actions || [], conditions),
};
};
export default createDefaultForm;

View File

@ -1,13 +1,20 @@
import { chain } from 'lodash';
const replaceName = name => name.split(' ').join('-');
const formatLayout = (layout, groupByKey) => {
return chain(layout)
.groupBy(groupByKey)
.map((item, itemName) => ({
category: itemName,
categoryId: replaceName(itemName),
childrenForm: chain(item)
.groupBy('subCategory')
.map((actions, subCategoryName) => ({ subCategoryName, actions }))
.map((actions, subCategoryName) => ({
subCategoryName,
subCategoryId: replaceName(subCategoryName),
actions,
}))
.value(),
}))
.value();

View File

@ -8,7 +8,15 @@ import { useIntl } from 'react-intl';
import SubCategory from '../SubCategory';
import RowStyle from './Wrapper';
const PermissionRow = ({ childrenForm, kind, name, isOpen, isWhite, onOpenCategory }) => {
const PermissionRow = ({
childrenForm,
kind,
name,
isOpen,
isWhite,
onOpenCategory,
pathToData,
}) => {
const { formatMessage } = useIntl();
const handleClick = () => {
@ -23,12 +31,7 @@ const PermissionRow = ({ childrenForm, kind, name, isOpen, isWhite, onOpenCatego
return (
<RowContainer isWhite={isWhite}>
<RowStyle
isWhite={isWhite}
isActive={isOpen}
// key={permissions.category}
onClick={handleClick}
>
<RowStyle isWhite={isWhite} isActive={isOpen} onClick={handleClick}>
<Flex alignItems="center" justifyContent="space-between">
<div>
<Text color="grey" fontWeight="bold" fontSize="xs" textTransform="uppercase">
@ -47,8 +50,13 @@ const PermissionRow = ({ childrenForm, kind, name, isOpen, isWhite, onOpenCatego
{isOpen && (
<PermissionsWrapper isWhite={isWhite}>
{childrenForm.map(({ actions, subCategoryName }) => (
<SubCategory categoryName={subCategoryName} key={subCategoryName} actions={actions} />
{childrenForm.map(({ actions, subCategoryName, subCategoryId }) => (
<SubCategory
categoryName={subCategoryName}
key={subCategoryName}
actions={actions}
pathToData={[...pathToData, subCategoryId]}
/>
))}
</PermissionsWrapper>
)}
@ -65,6 +73,7 @@ PermissionRow.propTypes = {
kind: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
onOpenCategory: PropTypes.func.isRequired,
pathToData: PropTypes.array.isRequired,
};
export default PermissionRow;

View File

@ -1,9 +1,12 @@
import React from 'react';
import React, { useMemo } from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { Flex, Padded, Text, Checkbox } from '@buffetjs/core';
import { useIntl } from 'react-intl';
import { BaselineAlignment } from 'strapi-helper-plugin';
import { get } from 'lodash';
import { usePermissionsDataManager } from '../../contexts/PermissionsDataManagerContext';
import { getCheckboxState, removeConditionKeyFromData } from '../../utils';
import ConditionsButton from '../../ConditionsButton';
import CheckboxWrapper from './CheckboxWrapper';
import Wrapper from './Wrapper';
@ -16,9 +19,25 @@ const Border = styled.div`
padding: 0px 10px;
`;
const SubCategory = ({ categoryName, actions }) => {
const SubCategory = ({ categoryName, actions, pathToData }) => {
const {
modifiedData,
onChangeParentCheckbox,
onChangeSimpleCheckbox,
} = usePermissionsDataManager();
const { formatMessage } = useIntl();
const mainData = get(modifiedData, pathToData, {});
const dataWithoutCondition = useMemo(() => {
return Object.keys(mainData).reduce((acc, current) => {
acc[current] = removeConditionKeyFromData(mainData[current]);
return acc;
}, {});
}, [mainData]);
const { hasAllActionsSelected, hasSomeActionsSelected } = getCheckboxState(dataWithoutCondition);
return (
<>
<Wrapper>
@ -38,31 +57,36 @@ const SubCategory = ({ categoryName, actions }) => {
<Padded left size="sm">
<BaselineAlignment top size="1px" />
<Checkbox
// name={`select-all-${categoryName}`}
name="todo"
name={pathToData.join('..')}
message={formatMessage({ id: 'app.utils.select-all' })}
disabled
onChange={() => {}}
someChecked={false}
value={false}
// TODO
disabled={false}
onChange={onChangeParentCheckbox}
someChecked={hasSomeActionsSelected}
value={hasAllActionsSelected}
/>
</Padded>
</Flex>
<BaselineAlignment top size="1px" />
<Padded top size="xs">
<Flex flexWrap="wrap">
{actions.map(sc => (
<CheckboxWrapper disabled hasConditions={false} key={sc.action}>
<Checkbox
value={false}
name="todo"
// TODO
disabled={false}
message={sc.displayName}
onChange={() => {}}
/>
</CheckboxWrapper>
))}
{actions.map(sc => {
const checkboxName = [...pathToData, sc.action, 'enabled'];
const value = get(modifiedData, checkboxName, false);
return (
<CheckboxWrapper disabled hasConditions={false} key={sc.action}>
<Checkbox
name={checkboxName.join('..')}
// TODO
disabled={false}
message={sc.displayName}
onChange={onChangeSimpleCheckbox}
value={value}
/>
</CheckboxWrapper>
);
})}
</Flex>
<ConditionsButtonWrapper disabled={false} hasConditions={false}>
<ConditionsButton hasConditions={false} onClick={() => {}} />
@ -74,8 +98,9 @@ const SubCategory = ({ categoryName, actions }) => {
};
SubCategory.propTypes = {
categoryName: PropTypes.string.isRequired,
actions: PropTypes.array.isRequired,
categoryName: PropTypes.string.isRequired,
pathToData: PropTypes.array.isRequired,
};
export default SubCategory;

View File

@ -14,10 +14,7 @@ const PluginsAndSettingsPermissions = ({ kind, layout }) => {
return (
<ListWrapper>
<Padded left right size="md">
{layout.map(({ category, childrenForm }, index) => {
// console.log({ permissionLayout });
console.log({ category, childrenForm });
{layout.map(({ category, categoryId, childrenForm }, index) => {
return (
<PermissionRow
key={category}
@ -27,7 +24,7 @@ const PluginsAndSettingsPermissions = ({ kind, layout }) => {
isWhite={index % 2 === 1}
name={category}
onOpenCategory={handleOpenCategory}
// permissions={permissionLayout}
pathToData={[kind, categoryId]}
/>
);
})}
@ -41,6 +38,7 @@ PluginsAndSettingsPermissions.propTypes = {
layout: PropTypes.arrayOf(
PropTypes.shape({
category: PropTypes.string.isRequired,
categoryId: PropTypes.string.isRequired,
childrenForm: PropTypes.arrayOf(
PropTypes.shape({
actions: PropTypes.array.isRequired,