mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-23 01:16:27 +02:00
fix: refine project actions form (#6242)
https://linear.app/unleash/issue/2-1934/refine-the-actions-form-uiux First effort in refining the project actions form to look slightly more like the design, including some refactors. 
This commit is contained in:
parent
6a9f80c554
commit
7a699cf68c
@ -1,58 +0,0 @@
|
|||||||
import { Box, styled } from '@mui/material';
|
|
||||||
|
|
||||||
export const StyledInnerBox = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
backgroundColor: theme.palette.background.default,
|
|
||||||
border: `1px solid ${theme.palette.divider}`,
|
|
||||||
padding: theme.spacing(2),
|
|
||||||
borderRadius: `${theme.shape.borderRadiusMedium}px`,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledInnerBoxHeader = styled('div')(({ theme }) => ({
|
|
||||||
marginLeft: 'auto',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
[theme.breakpoints.down('sm')]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
// row for inner containers
|
|
||||||
export const StyledRow = styled('div')({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: '100%',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const StyledCol = styled('div')({
|
|
||||||
flex: 1,
|
|
||||||
margin: '0 4px',
|
|
||||||
});
|
|
||||||
|
|
||||||
const StyledBoxContent = styled('div')(({ theme }) => ({
|
|
||||||
padding: theme.spacing(0.75, 1),
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
fontSize: theme.fontSizes.smallerBody,
|
|
||||||
backgroundColor: theme.palette.seen.primary,
|
|
||||||
borderRadius: theme.shape.borderRadius,
|
|
||||||
position: 'absolute',
|
|
||||||
zIndex: theme.zIndex.fab,
|
|
||||||
top: '50%',
|
|
||||||
left: theme.spacing(2),
|
|
||||||
transform: 'translateY(-50%)',
|
|
||||||
lineHeight: 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const BoxSeparator: React.FC = ({ children }) => {
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
height: 1.5,
|
|
||||||
position: 'relative',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<StyledBoxContent>{children}</StyledBoxContent>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,19 +1,22 @@
|
|||||||
import { IconButton, Tooltip } from '@mui/material';
|
import { IconButton, Tooltip, styled } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { Fragment } from 'react';
|
|
||||||
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
|
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
|
||||||
import { Delete } from '@mui/icons-material';
|
import { Delete } from '@mui/icons-material';
|
||||||
import { useProjectEnvironments } from 'hooks/api/getters/useProjectEnvironments/useProjectEnvironments';
|
import { useProjectEnvironments } from 'hooks/api/getters/useProjectEnvironments/useProjectEnvironments';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
||||||
import {
|
|
||||||
BoxSeparator,
|
|
||||||
StyledCol,
|
|
||||||
StyledInnerBoxHeader,
|
|
||||||
StyledRow,
|
|
||||||
StyledInnerBox,
|
|
||||||
} from './InnerContainerBox';
|
|
||||||
import { ActionsActionState } from './useProjectActionsForm';
|
import { ActionsActionState } from './useProjectActionsForm';
|
||||||
|
import { ProjectActionsFormItem } from './ProjectActionsFormItem';
|
||||||
|
|
||||||
|
const StyledItemRow = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
width: '100%',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledFieldContainer = styled('div')({
|
||||||
|
flex: 1,
|
||||||
|
});
|
||||||
|
|
||||||
export const ProjectActionsActionItem = ({
|
export const ProjectActionsActionItem = ({
|
||||||
action,
|
action,
|
||||||
@ -30,25 +33,24 @@ export const ProjectActionsActionItem = ({
|
|||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const environments = useProjectEnvironments(projectId);
|
const environments = useProjectEnvironments(projectId);
|
||||||
const { features } = useFeatureSearch({ project: `IS:${projectId}` });
|
const { features } = useFeatureSearch({ project: `IS:${projectId}` });
|
||||||
return (
|
|
||||||
<Fragment>
|
const header = (
|
||||||
<ConditionallyRender
|
<>
|
||||||
condition={index > 0}
|
|
||||||
show={<BoxSeparator>THEN</BoxSeparator>}
|
|
||||||
/>
|
|
||||||
<StyledInnerBox>
|
|
||||||
<StyledRow>
|
|
||||||
<span>Action {index + 1}</span>
|
<span>Action {index + 1}</span>
|
||||||
<StyledInnerBoxHeader>
|
<div>
|
||||||
<Tooltip title='Delete action' arrow>
|
<Tooltip title='Delete action' arrow>
|
||||||
<IconButton onClick={onDelete}>
|
<IconButton onClick={onDelete}>
|
||||||
<Delete />
|
<Delete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</StyledInnerBoxHeader>
|
</div>
|
||||||
</StyledRow>
|
</>
|
||||||
<StyledRow>
|
);
|
||||||
<StyledCol>
|
|
||||||
|
return (
|
||||||
|
<ProjectActionsFormItem index={index} header={header} separator='THEN'>
|
||||||
|
<StyledItemRow>
|
||||||
|
<StyledFieldContainer>
|
||||||
<GeneralSelect
|
<GeneralSelect
|
||||||
label='Action'
|
label='Action'
|
||||||
name='action'
|
name='action'
|
||||||
@ -71,8 +73,8 @@ export const ProjectActionsActionItem = ({
|
|||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</StyledCol>
|
</StyledFieldContainer>
|
||||||
<StyledCol>
|
<StyledFieldContainer>
|
||||||
<GeneralSelect
|
<GeneralSelect
|
||||||
label='Environment'
|
label='Environment'
|
||||||
name='environment'
|
name='environment'
|
||||||
@ -92,8 +94,8 @@ export const ProjectActionsActionItem = ({
|
|||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</StyledCol>
|
</StyledFieldContainer>
|
||||||
<StyledCol>
|
<StyledFieldContainer>
|
||||||
<GeneralSelect
|
<GeneralSelect
|
||||||
label='Flag name'
|
label='Flag name'
|
||||||
name='flag'
|
name='flag'
|
||||||
@ -113,9 +115,8 @@ export const ProjectActionsActionItem = ({
|
|||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</StyledCol>
|
</StyledFieldContainer>
|
||||||
</StyledRow>
|
</StyledItemRow>
|
||||||
</StyledInnerBox>
|
</ProjectActionsFormItem>
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
import { Badge, IconButton, Tooltip, styled } from '@mui/material';
|
import { Badge, IconButton, Tooltip, styled } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { ActionsFilterState } from './useProjectActionsForm';
|
import { ActionsFilterState } from './useProjectActionsForm';
|
||||||
import { Fragment } from 'react';
|
|
||||||
import { Delete } from '@mui/icons-material';
|
import { Delete } from '@mui/icons-material';
|
||||||
import Input from 'component/common/Input/Input';
|
import Input from 'component/common/Input/Input';
|
||||||
import {
|
import { ProjectActionsFormItem } from './ProjectActionsFormItem';
|
||||||
BoxSeparator,
|
|
||||||
StyledInnerBoxHeader,
|
|
||||||
StyledRow,
|
|
||||||
StyledInnerBox,
|
|
||||||
} from './InnerContainerBox';
|
|
||||||
|
|
||||||
const StyledInput = styled(Input)(() => ({
|
const StyledInputContainer = styled('div')({
|
||||||
|
flex: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledInput = styled(Input)({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}));
|
});
|
||||||
|
|
||||||
const StyledBadge = styled(Badge)(({ theme }) => ({
|
const StyledBadge = styled(Badge)(({ theme }) => ({
|
||||||
color: 'primary',
|
margin: theme.spacing(0, 1),
|
||||||
margin: theme.spacing(1),
|
fontSize: theme.fontSizes.mainHeader,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ProjectActionsFilterItem = ({
|
export const ProjectActionsFilterItem = ({
|
||||||
@ -32,24 +29,23 @@ export const ProjectActionsFilterItem = ({
|
|||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { parameter, value } = filter;
|
const { parameter, value } = filter;
|
||||||
return (
|
|
||||||
<Fragment>
|
const header = (
|
||||||
<ConditionallyRender
|
<>
|
||||||
condition={index > 0}
|
|
||||||
show={<BoxSeparator>AND</BoxSeparator>}
|
|
||||||
/>
|
|
||||||
<StyledInnerBox>
|
|
||||||
<StyledRow>
|
|
||||||
<span>Filter {index + 1}</span>
|
<span>Filter {index + 1}</span>
|
||||||
<StyledInnerBoxHeader>
|
<div>
|
||||||
<Tooltip title='Delete filter' arrow>
|
<Tooltip title='Delete filter' arrow>
|
||||||
<IconButton type='button' onClick={onDelete}>
|
<IconButton onClick={onDelete}>
|
||||||
<Delete />
|
<Delete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</StyledInnerBoxHeader>
|
</div>
|
||||||
</StyledRow>
|
</>
|
||||||
<StyledRow>
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ProjectActionsFormItem index={index} header={header}>
|
||||||
|
<StyledInputContainer>
|
||||||
<StyledInput
|
<StyledInput
|
||||||
label='Parameter'
|
label='Parameter'
|
||||||
value={parameter}
|
value={parameter}
|
||||||
@ -60,7 +56,9 @@ export const ProjectActionsFilterItem = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</StyledInputContainer>
|
||||||
<StyledBadge>=</StyledBadge>
|
<StyledBadge>=</StyledBadge>
|
||||||
|
<StyledInputContainer>
|
||||||
<StyledInput
|
<StyledInput
|
||||||
label='Value'
|
label='Value'
|
||||||
value={value}
|
value={value}
|
||||||
@ -71,8 +69,7 @@ export const ProjectActionsFilterItem = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledRow>
|
</StyledInputContainer>
|
||||||
</StyledInnerBox>
|
</ProjectActionsFormItem>
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Alert, Box, Button, Link, styled } from '@mui/material';
|
import { Alert, Button, Divider, Link, styled } from '@mui/material';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import Input from 'component/common/Input/Input';
|
import Input from 'component/common/Input/Input';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
|
||||||
import { FormSwitch } from 'component/common/FormSwitch/FormSwitch';
|
import { FormSwitch } from 'component/common/FormSwitch/FormSwitch';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import {
|
import {
|
||||||
@ -16,9 +15,9 @@ import { useMemo } from 'react';
|
|||||||
import GeneralSelect, {} from 'component/common/GeneralSelect/GeneralSelect';
|
import GeneralSelect, {} from 'component/common/GeneralSelect/GeneralSelect';
|
||||||
import { Add } from '@mui/icons-material';
|
import { Add } from '@mui/icons-material';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { StyledRow } from './InnerContainerBox';
|
|
||||||
import { ProjectActionsActionItem } from './ProjectActionsActionItem';
|
import { ProjectActionsActionItem } from './ProjectActionsActionItem';
|
||||||
import { ProjectActionsFilterItem } from './ProjectActionsFilterItem';
|
import { ProjectActionsFilterItem } from './ProjectActionsFilterItem';
|
||||||
|
import { ProjectActionsFormStep } from './ProjectActionsFormStep';
|
||||||
|
|
||||||
const StyledServiceAccountAlert = styled(Alert)(({ theme }) => ({
|
const StyledServiceAccountAlert = styled(Alert)(({ theme }) => ({
|
||||||
marginBottom: theme.spacing(4),
|
marginBottom: theme.spacing(4),
|
||||||
@ -44,27 +43,20 @@ const StyledInput = styled(Input)(() => ({
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledBadge = styled(Badge)(({ theme }) => ({
|
const StyledSecondaryDescription = styled('p')(({ theme }) => ({
|
||||||
color: 'primary',
|
|
||||||
margin: 'auto',
|
|
||||||
marginBottom: theme.spacing(1.5),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledBox = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
color: theme.palette.text.secondary,
|
||||||
backgroundColor: theme.palette.background.elevation1,
|
fontSize: theme.fontSizes.smallBody,
|
||||||
marginTop: theme.spacing(2),
|
|
||||||
padding: theme.spacing(2),
|
|
||||||
borderRadius: theme.shape.borderRadiusMedium,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Step = ({ name, children }: any) => (
|
const StyledButtonContainer = styled('div')(({ theme }) => ({
|
||||||
<StyledBox>
|
marginTop: theme.spacing(2),
|
||||||
<StyledBadge color='secondary'>{name}</StyledBadge>
|
}));
|
||||||
{children}
|
|
||||||
</StyledBox>
|
const StyledDivider = styled(Divider)(({ theme }) => ({
|
||||||
);
|
margin: theme.spacing(3, 0),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
interface IProjectActionsFormProps {
|
interface IProjectActionsFormProps {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@ -101,6 +93,7 @@ export const ProjectActionsForm = ({
|
|||||||
validateName,
|
validateName,
|
||||||
validated,
|
validated,
|
||||||
}: IProjectActionsFormProps) => {
|
}: IProjectActionsFormProps) => {
|
||||||
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const { serviceAccounts, loading: serviceAccountsLoading } =
|
const { serviceAccounts, loading: serviceAccountsLoading } =
|
||||||
useServiceAccounts();
|
useServiceAccounts();
|
||||||
const { incomingWebhooks, loading: incomingWebhooksLoading } =
|
const { incomingWebhooks, loading: incomingWebhooksLoading } =
|
||||||
@ -177,7 +170,7 @@ export const ProjectActionsForm = ({
|
|||||||
}, [serviceAccountsLoading, serviceAccounts]);
|
}, [serviceAccountsLoading, serviceAccounts]);
|
||||||
|
|
||||||
const showErrors = validated && Object.values(errors).some(Boolean);
|
const showErrors = validated && Object.values(errors).some(Boolean);
|
||||||
const projectId = useRequiredPathParam('projectId');
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -218,7 +211,7 @@ export const ProjectActionsForm = ({
|
|||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Step name='Trigger'>
|
<ProjectActionsFormStep name='Trigger'>
|
||||||
<StyledInputDescription>
|
<StyledInputDescription>
|
||||||
Create incoming webhooks from
|
Create incoming webhooks from
|
||||||
<RouterLink to='/integrations/incoming-webhooks'>
|
<RouterLink to='/integrations/incoming-webhooks'>
|
||||||
@ -235,9 +228,13 @@ export const ProjectActionsForm = ({
|
|||||||
setSourceId(parseInt(v));
|
setSourceId(parseInt(v));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Step>
|
</ProjectActionsFormStep>
|
||||||
|
|
||||||
<Step name='When this'>
|
<ProjectActionsFormStep name='When this' verticalConnector>
|
||||||
|
<StyledSecondaryDescription>
|
||||||
|
If no filters are defined then the action will be triggered
|
||||||
|
every time the incoming webhook is called.
|
||||||
|
</StyledSecondaryDescription>
|
||||||
{filters.map((filter, index) => (
|
{filters.map((filter, index) => (
|
||||||
<ProjectActionsFilterItem
|
<ProjectActionsFilterItem
|
||||||
key={filter.id}
|
key={filter.id}
|
||||||
@ -251,11 +248,8 @@ export const ProjectActionsForm = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<StyledButtonContainer>
|
||||||
<hr />
|
|
||||||
<StyledRow>
|
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
|
||||||
startIcon={<Add />}
|
startIcon={<Add />}
|
||||||
onClick={addFilter}
|
onClick={addFilter}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
@ -263,10 +257,10 @@ export const ProjectActionsForm = ({
|
|||||||
>
|
>
|
||||||
Add filter
|
Add filter
|
||||||
</Button>
|
</Button>
|
||||||
</StyledRow>
|
</StyledButtonContainer>
|
||||||
</Step>
|
</ProjectActionsFormStep>
|
||||||
|
|
||||||
<Step name='Do these action(s)'>
|
<ProjectActionsFormStep name='Do these action(s)' verticalConnector>
|
||||||
<StyledInputDescription>
|
<StyledInputDescription>
|
||||||
Create service accounts from
|
Create service accounts from
|
||||||
<RouterLink to='/admin/service-accounts'>
|
<RouterLink to='/admin/service-accounts'>
|
||||||
@ -283,7 +277,7 @@ export const ProjectActionsForm = ({
|
|||||||
setActorId(parseInt(v));
|
setActorId(parseInt(v));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<hr />
|
<StyledDivider />
|
||||||
{actions.map((action, index) => (
|
{actions.map((action, index) => (
|
||||||
<ProjectActionsActionItem
|
<ProjectActionsActionItem
|
||||||
index={index}
|
index={index}
|
||||||
@ -297,10 +291,8 @@ export const ProjectActionsForm = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<hr />
|
<StyledButtonContainer>
|
||||||
<StyledRow>
|
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
|
||||||
startIcon={<Add />}
|
startIcon={<Add />}
|
||||||
onClick={() => addAction(projectId)}
|
onClick={() => addAction(projectId)}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
@ -308,8 +300,8 @@ export const ProjectActionsForm = ({
|
|||||||
>
|
>
|
||||||
Add action
|
Add action
|
||||||
</Button>
|
</Button>
|
||||||
</StyledRow>
|
</StyledButtonContainer>
|
||||||
</Step>
|
</ProjectActionsFormStep>
|
||||||
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={showErrors}
|
condition={showErrors}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import { styled } from '@mui/material';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
const StyledItem = styled('div')(({ theme }) => ({
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
position: 'relative',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledItemSeparator = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(0.75, 1),
|
||||||
|
fontSize: theme.fontSizes.smallerBody,
|
||||||
|
backgroundColor: theme.palette.seen.primary,
|
||||||
|
borderRadius: theme.shape.borderRadius,
|
||||||
|
position: 'absolute',
|
||||||
|
zIndex: theme.zIndex.fab,
|
||||||
|
top: theme.spacing(-2),
|
||||||
|
left: theme.spacing(2),
|
||||||
|
lineHeight: 1,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledInnerBox = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
border: `1px solid ${theme.palette.divider}`,
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
paddingTop: theme.spacing(1),
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledRow = styled('div')({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledHeaderRow = styled(StyledRow)(({ theme }) => ({
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface IProjectActionsFormItemProps {
|
||||||
|
index: number;
|
||||||
|
header: ReactNode;
|
||||||
|
separator?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProjectActionsFormItem = ({
|
||||||
|
index,
|
||||||
|
header,
|
||||||
|
separator = 'AND',
|
||||||
|
children,
|
||||||
|
}: IProjectActionsFormItemProps) => {
|
||||||
|
return (
|
||||||
|
<StyledItem>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={index > 0}
|
||||||
|
show={<StyledItemSeparator>{separator}</StyledItemSeparator>}
|
||||||
|
/>
|
||||||
|
<StyledInnerBox>
|
||||||
|
<StyledHeaderRow>{header}</StyledHeaderRow>
|
||||||
|
<StyledRow>{children}</StyledRow>
|
||||||
|
</StyledInnerBox>
|
||||||
|
</StyledItem>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,49 @@
|
|||||||
|
import { Box, Divider, styled } from '@mui/material';
|
||||||
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
const StyledBadge = styled(Badge)(({ theme }) => ({
|
||||||
|
margin: 'auto',
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledBox = styled(Box, {
|
||||||
|
shouldForwardProp: (prop) => prop !== 'verticalConnector',
|
||||||
|
})<{ verticalConnector?: boolean }>(({ theme, verticalConnector }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
backgroundColor: theme.palette.background.elevation1,
|
||||||
|
marginTop: verticalConnector ? 0 : theme.spacing(3),
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledVerticalConnector = styled(Divider)(({ theme }) => ({
|
||||||
|
margin: 'auto',
|
||||||
|
width: 1,
|
||||||
|
height: theme.spacing(3),
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface IProjectActionsFormStepProps {
|
||||||
|
name: string;
|
||||||
|
verticalConnector?: boolean;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProjectActionsFormStep = ({
|
||||||
|
name,
|
||||||
|
verticalConnector,
|
||||||
|
children,
|
||||||
|
}: IProjectActionsFormStepProps) => (
|
||||||
|
<>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(verticalConnector)}
|
||||||
|
show={<StyledVerticalConnector orientation='vertical' />}
|
||||||
|
/>
|
||||||
|
<StyledBox verticalConnector={verticalConnector}>
|
||||||
|
<StyledBadge color='secondary'>{name}</StyledBadge>
|
||||||
|
{children}
|
||||||
|
</StyledBox>
|
||||||
|
</>
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user