Form done, WIP collection type

This commit is contained in:
bulby97 2021-08-17 15:49:07 +02:00
parent 9f7208db9d
commit 54b2b64b43
7 changed files with 196 additions and 123 deletions

View File

@ -1,9 +1,9 @@
import React, { useCallback, useMemo } from 'react'; import { Box } from '@strapi/parts';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { useCallback, useMemo } from 'react';
import Collapse from './Collapse'; import Collapse from './Collapse';
import CollapsePropertyMatrix from './CollapsePropertyMatrix'; import CollapsePropertyMatrix from './CollapsePropertyMatrix';
import { getAvailableActions } from './utils'; import { getAvailableActions } from './utils';
import Wrapper from './Wrapper';
const ContentTypeCollapse = ({ const ContentTypeCollapse = ({
allActions, allActions,
@ -27,7 +27,7 @@ const ContentTypeCollapse = ({
const isOdd = useMemo(() => index % 2 !== 0, [index]); const isOdd = useMemo(() => index % 2 !== 0, [index]);
return ( return (
<Wrapper withMargin={isOdd}> <Box>
<Collapse <Collapse
availableActions={availableActions} availableActions={availableActions}
isActive={isActive} isActive={isActive}
@ -53,7 +53,7 @@ const ContentTypeCollapse = ({
/> />
); );
})} })}
</Wrapper> </Box>
); );
}; };

View File

@ -1,14 +1,12 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Padded } from '@buffetjs/core'; import { Box } from '@strapi/parts';
import ContentTypeCollapses from '../ContentTypeCollapses'; import ContentTypeCollapses from '../ContentTypeCollapses';
import GlobalActions from '../GlobalActions'; import GlobalActions from '../GlobalActions';
import Wrapper from './Wrapper';
const ContentTypes = ({ isFormDisabled, kind, layout: { actions, subjects } }) => { const ContentTypes = ({ isFormDisabled, kind, layout: { actions, subjects } }) => {
return ( return (
<Wrapper> <Box background="neutral0">
<Padded left right bottom size="md">
<GlobalActions actions={actions} kind={kind} isFormDisabled={isFormDisabled} /> <GlobalActions actions={actions} kind={kind} isFormDisabled={isFormDisabled} />
<ContentTypeCollapses <ContentTypeCollapses
actions={actions} actions={actions}
@ -16,8 +14,7 @@ const ContentTypes = ({ isFormDisabled, kind, layout: { actions, subjects } }) =
pathToData={kind} pathToData={kind}
subjects={subjects} subjects={subjects}
/> />
</Padded> </Box>
</Wrapper>
); );
}; };

View File

@ -1,9 +1,9 @@
import styled from 'styled-components'; import styled from 'styled-components';
const Wrapper = styled.div` const Wrapper = styled.div`
padding-left: 165px; padding-left: 200px;
padding-bottom: 25px; padding-bottom: ${({ theme }) => theme.spaces[4]};
padding-top: 26px; padding-top: ${({ theme }) => theme.spaces[6]};
${({ disabled, theme }) => ${({ disabled, theme }) =>
` `
input[type='checkbox'] { input[type='checkbox'] {

View File

@ -1,14 +1,30 @@
import React, { memo, useMemo } from 'react'; import { Box, Checkbox, Stack } from '@strapi/parts';
import IS_DISABLED from 'ee_else_ce/components/Roles/GlobalActions/utils/constants';
import { get } from 'lodash'; import { get } from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Flex } from '@buffetjs/core'; import React, { memo, useMemo } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import IS_DISABLED from 'ee_else_ce/components/Roles/GlobalActions/utils/constants'; import styled from 'styled-components';
import { usePermissionsDataManager } from '../../../hooks'; import { usePermissionsDataManager } from '../../../hooks';
import CheckboxWithCondition from '../CheckboxWithCondition';
import { findDisplayedActions, getCheckboxesState } from './utils'; import { findDisplayedActions, getCheckboxesState } from './utils';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
const Label = styled(Box)`
font-size: ${11 / 16}rem;
text-transform: uppercase;
color: ${({ theme }) => theme.colors.neutral500};
font-weight: bold;
`;
// ! TODO - Remove dflex, and fcolumn when strapi/parts is updated
const CenteredStack = styled(Stack)`
align-items: center;
justify-content: center;
display: flex;
flex-direction: column;
width: 120px;
`;
const GlobalActions = ({ actions, isFormDisabled, kind }) => { const GlobalActions = ({ actions, isFormDisabled, kind }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const { modifiedData, onChangeCollectionTypeGlobalActionCheckbox } = usePermissionsDataManager(); const { modifiedData, onChangeCollectionTypeGlobalActionCheckbox } = usePermissionsDataManager();
@ -23,26 +39,29 @@ const GlobalActions = ({ actions, isFormDisabled, kind }) => {
return ( return (
<Wrapper disabled={isFormDisabled}> <Wrapper disabled={isFormDisabled}>
<Flex> <Stack horizontal size={4}>
{displayedActions.map(({ label, actionId }) => { {displayedActions.map(({ label, actionId }) => {
return ( return (
<CheckboxWithCondition <CenteredStack key={actionId} size={3}>
key={actionId} <Label>
disabled={isFormDisabled || IS_DISABLED} {formatMessage({
message={formatMessage({
id: `Settings.roles.form.permissions.${label.toLowerCase()}`, id: `Settings.roles.form.permissions.${label.toLowerCase()}`,
defaultMessage: label, defaultMessage: label,
})} })}
onChange={({ target: { value } }) => { </Label>
<Checkbox
disabled={isFormDisabled || IS_DISABLED}
onValueChange={value => {
onChangeCollectionTypeGlobalActionCheckbox(kind, actionId, value); onChangeCollectionTypeGlobalActionCheckbox(kind, actionId, value);
}} }}
name={actionId} name={actionId}
value={get(checkboxesState, [actionId, 'hasAllActionsSelected'], false)} value={get(checkboxesState, [actionId, 'hasAllActionsSelected'], false)}
someChecked={get(checkboxesState, [actionId, 'hasSomeActionsSelected'], false)} indeterminate={get(checkboxesState, [actionId, 'hasSomeActionsSelected'], false)}
/> />
</CenteredStack>
); );
})} })}
</Flex> </Stack>
</Wrapper> </Wrapper>
); );
}; };

View File

@ -1,8 +1,9 @@
import React, { forwardRef, memo, useCallback, useImperativeHandle, useReducer } from 'react'; import React, { forwardRef, memo, useCallback, useImperativeHandle, useReducer } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { difference } from '@strapi/helper-plugin'; import { difference } from '@strapi/helper-plugin';
import { TabGroup, Tabs, TabPanels, Tab, TabPanel, Box } from '@strapi/parts';
import { useIntl } from 'react-intl';
import { has, isEmpty } from 'lodash'; import { has, isEmpty } from 'lodash';
import Tabs from '../Tabs';
import PermissionsDataManagerProvider from '../PermissionsDataManagerProvider'; import PermissionsDataManagerProvider from '../PermissionsDataManagerProvider';
import ContentTypes from '../ContentTypes'; import ContentTypes from '../ContentTypes';
import PluginsAndSettings from '../PluginsAndSettings'; import PluginsAndSettings from '../PluginsAndSettings';
@ -15,6 +16,7 @@ const Permissions = forwardRef(({ layout, isFormDisabled, permissions }, ref) =>
const [{ initialData, layouts, modifiedData }, dispatch] = useReducer(reducer, initialState, () => const [{ initialData, layouts, modifiedData }, dispatch] = useReducer(reducer, initialState, () =>
init(layout, permissions) init(layout, permissions)
); );
const { formatMessage } = useIntl();
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
@ -106,28 +108,49 @@ const Permissions = forwardRef(({ layout, isFormDisabled, permissions }, ref) =>
onChangeCollectionTypeGlobalActionCheckbox: handleChangeCollectionTypeGlobalActionCheckbox, onChangeCollectionTypeGlobalActionCheckbox: handleChangeCollectionTypeGlobalActionCheckbox,
}} }}
> >
<Tabs tabsLabel={TAB_LABELS}> <TabGroup label="Some stuff for the label" id="tabs">
<Tabs>
{TAB_LABELS.map(tabLabel => (
<Tab key={tabLabel.id}>{formatMessage({ id: tabLabel.labelId })}</Tab>
))}
</Tabs>
<TabPanels>
<TabPanel>
<ContentTypes <ContentTypes
layout={layouts.collectionTypes} layout={layouts.collectionTypes}
kind="collectionTypes" kind="collectionTypes"
isFormDisabled={isFormDisabled} isFormDisabled={isFormDisabled}
/> />
</TabPanel>
<TabPanel>
<Box padding={4} background="neutral0">
<ContentTypes <ContentTypes
layout={layouts.singleTypes} layout={layouts.singleTypes}
kind="singleTypes" kind="singleTypes"
isFormDisabled={isFormDisabled} isFormDisabled={isFormDisabled}
/> />
</Box>
</TabPanel>
<TabPanel>
<Box padding={4} background="neutral0">
<PluginsAndSettings <PluginsAndSettings
layout={layouts.plugins} layout={layouts.plugins}
kind="plugins" kind="plugins"
isFormDisabled={isFormDisabled} isFormDisabled={isFormDisabled}
/> />
</Box>
</TabPanel>
<TabPanel>
<Box padding={4} background="neutral0">
<PluginsAndSettings <PluginsAndSettings
layout={layouts.settings} layout={layouts.settings}
kind="settings" kind="settings"
isFormDisabled={isFormDisabled} isFormDisabled={isFormDisabled}
/> />
</Tabs> </Box>
</TabPanel>
</TabPanels>
</TabGroup>
</PermissionsDataManagerProvider> </PermissionsDataManagerProvider>
); );
}); });

View File

@ -127,7 +127,7 @@
"Settings.roles.create.title": "Create a role", "Settings.roles.create.title": "Create a role",
"Settings.roles.created": "Role created", "Settings.roles.created": "Role created",
"Settings.roles.edit.title": "Edit a role", "Settings.roles.edit.title": "Edit a role",
"Settings.roles.form.button.users-with-role": "Users with this role", "Settings.roles.form.button.users-with-role": "{number} users with this role",
"Settings.roles.form.created": "Created", "Settings.roles.form.created": "Created",
"Settings.roles.form.description": "Name and description of the role", "Settings.roles.form.description": "Name and description of the role",
"Settings.roles.form.input.description": "Description", "Settings.roles.form.input.description": "Description",

View File

@ -1,24 +1,32 @@
import { Padded } from '@buffetjs/core';
import { import {
BaselineAlignment,
CheckPagePermissions, CheckPagePermissions,
request, request,
useNotification, useNotification,
useOverlayBlocker, useOverlayBlocker,
useTracking, useTracking,
} from '@strapi/helper-plugin'; } from '@strapi/helper-plugin';
import { Button, HeaderLayout, Stack } from '@strapi/parts'; import {
Box,
Button,
ContentLayout,
Grid,
GridItem,
HeaderLayout,
Row,
Stack,
Text,
Textarea,
TextInput,
} from '@strapi/parts';
import { Formik } from 'formik'; import { Formik } from 'formik';
import { get, isEmpty } from 'lodash'; import { get, isEmpty } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useHistory, useRouteMatch } from 'react-router-dom'; import { useHistory, useRouteMatch } from 'react-router-dom';
import FormCard from '../../../../../admin/src/components/FormBloc'; import styled from 'styled-components';
import { ButtonWithNumber } from '../../../../../admin/src/components/Roles';
import Permissions from '../../../../../admin/src/components/Roles/Permissions'; import Permissions from '../../../../../admin/src/components/Roles/Permissions';
import PageTitle from '../../../../../admin/src/components/SettingsPageTitle'; import PageTitle from '../../../../../admin/src/components/SettingsPageTitle';
import SizedInput from '../../../../../admin/src/components/SizedInput';
import { useFetchPermissionsLayout, useFetchRole } from '../../../../../admin/src/hooks'; import { useFetchPermissionsLayout, useFetchRole } from '../../../../../admin/src/hooks';
import adminPermissions from '../../../../../admin/src/permissions'; import adminPermissions from '../../../../../admin/src/permissions';
import schema from './utils/schema'; import schema from './utils/schema';
@ -91,14 +99,19 @@ const CreatePage = () => {
}); });
}; };
const actions = [ const UsersRoleNumber = styled.div`
<ButtonWithNumber number={0} onClick={() => console.log('Open user modal')} key="user-button"> border: 1px solid ${({ theme }) => theme.colors.primary200};
{formatMessage({ background: ${({ theme }) => theme.colors.primary100};
id: 'Settings.roles.form.button.users-with-role', padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[4]}`};
defaultMessage: 'Users with this role', color: ${({ theme }) => theme.colors.primary600};
})} border-radius: ${({ theme }) => theme.borderRadius};
</ButtonWithNumber>, font-size: ${12 / 16}rem;
]; font-width: bold;
`;
const FlexBox = styled(Box)`
flex: 1;
`;
const defaultDescription = `${formatMessage({ const defaultDescription = `${formatMessage({
id: 'Settings.roles.form.created', id: 'Settings.roles.form.created',
@ -120,6 +133,7 @@ const CreatePage = () => {
primaryAction={ primaryAction={
<Stack horizontal size={2}> <Stack horizontal size={2}>
<Button <Button
variant="secondary"
onClick={() => { onClick={() => {
handleReset(); handleReset();
permissionsRef.current.resetForm(); permissionsRef.current.resetForm();
@ -148,51 +162,71 @@ const CreatePage = () => {
})} })}
as="h1" as="h1"
/> />
<BaselineAlignment top size="3px" /> <ContentLayout>
<FormCard <Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
actions={actions} <Stack size={4}>
title={formatMessage({ <Row>
<FlexBox>
<Box>
<Text highlighted>
{formatMessage({
id: 'Settings.roles.form.title', id: 'Settings.roles.form.title',
defaultMessage: 'Details',
})} })}
subtitle={formatMessage({ </Text>
</Box>
<Box>
<Text textColor="neutral500" small>
{formatMessage({
id: 'Settings.roles.form.description', id: 'Settings.roles.form.description',
defaultMessage: 'Name and description of the role',
})} })}
> </Text>
<SizedInput </Box>
label="Settings.roles.form.input.name" </FlexBox>
defaultMessage="Name" <UsersRoleNumber>
{formatMessage(
{
id: 'Settings.roles.form.button.users-with-role',
},
{ number: 0 }
)}
</UsersRoleNumber>
</Row>
<Grid gap={4}>
<GridItem col={6}>
<TextInput
name="name" name="name"
type="text" error={errors.name && formatMessage({ id: errors.name })}
error={errors.name ? { id: errors.name } : null} label={formatMessage({ id: 'Settings.roles.form.input.name' })}
onChange={handleChange}
onBlur={handleBlur} onBlur={handleBlur}
value={values.name} value={values.name}
onChange={handleChange}
/> />
</GridItem>
<SizedInput <GridItem col={6}>
label="Settings.roles.form.input.description" <Textarea
defaultMessage="Description" label={formatMessage({ id: 'Settings.roles.form.input.description' })}
name="description" name="description"
type="textarea" error={errors.name && formatMessage({ id: errors.name })}
onBlur={handleBlur}
value={values.description}
onChange={handleChange} onChange={handleChange}
// Override the default height of the textarea onBlur={handleBlur}
style={{ height: 115 }} >
/> {values.description}
</FormCard> </Textarea>
</GridItem>
</Grid>
</Stack>
</Box>
{!isLayoutLoading && !isRoleLoading && ( {!isLayoutLoading && !isRoleLoading && (
<Padded top bottom size="md"> <Box paddingTop={6} paddingBottom={6}>
<Permissions <Permissions
isFormDisabled={false} isFormDisabled={false}
ref={permissionsRef} ref={permissionsRef}
permissions={rolePermissions} permissions={rolePermissions}
layout={permissionsLayout} layout={permissionsLayout}
/> />
</Padded> </Box>
)} )}
</ContentLayout>
</> </>
</form> </form>
)} )}