diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/InnerContainerBox.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/InnerContainerBox.tsx
deleted file mode 100644
index 4401114167..0000000000
--- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/InnerContainerBox.tsx
+++ /dev/null
@@ -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 (
-
- {children}
-
- );
-};
diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsActionItem.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsActionItem.tsx
index 29f20e9392..48911c78c3 100644
--- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsActionItem.tsx
+++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsActionItem.tsx
@@ -1,19 +1,22 @@
-import { IconButton, Tooltip } from '@mui/material';
-import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
-import { Fragment } from 'react';
+import { IconButton, Tooltip, styled } from '@mui/material';
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
import { Delete } from '@mui/icons-material';
import { useProjectEnvironments } from 'hooks/api/getters/useProjectEnvironments/useProjectEnvironments';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
-import {
- BoxSeparator,
- StyledCol,
- StyledInnerBoxHeader,
- StyledRow,
- StyledInnerBox,
-} from './InnerContainerBox';
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 = ({
action,
@@ -30,92 +33,90 @@ export const ProjectActionsActionItem = ({
const projectId = useRequiredPathParam('projectId');
const environments = useProjectEnvironments(projectId);
const { features } = useFeatureSearch({ project: `IS:${projectId}` });
+
+ const header = (
+ <>
+ Action {index + 1}
+
+
+
+
+
+
+
+ >
+ );
+
return (
-
- 0}
- show={THEN}
- />
-
-
- Action {index + 1}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ stateChanged({
+ ...action,
+ action: selected,
+ })
+ }
+ fullWidth
+ />
+
+
+ ({
+ label: env.name,
+ key: env.name,
+ }))}
+ value={action.executionParams.environment as string}
+ onChange={(selected) =>
+ stateChanged({
+ ...action,
+ executionParams: {
+ ...action.executionParams,
+ environment: selected,
},
- {
- label: 'Disable flag',
- key: 'TOGGLE_FEATURE_OFF',
+ })
+ }
+ fullWidth
+ />
+
+
+ ({
+ label: feature.name,
+ key: feature.name,
+ }))}
+ value={action.executionParams.featureName as string}
+ onChange={(selected) =>
+ stateChanged({
+ ...action,
+ executionParams: {
+ ...action.executionParams,
+ featureName: selected,
},
- ]}
- value={actionName}
- onChange={(selected) =>
- stateChanged({
- ...action,
- action: selected,
- })
- }
- fullWidth
- />
-
-
- ({
- label: env.name,
- key: env.name,
- }))}
- value={action.executionParams.environment as string}
- onChange={(selected) =>
- stateChanged({
- ...action,
- executionParams: {
- ...action.executionParams,
- environment: selected,
- },
- })
- }
- fullWidth
- />
-
-
- ({
- label: feature.name,
- key: feature.name,
- }))}
- value={action.executionParams.featureName as string}
- onChange={(selected) =>
- stateChanged({
- ...action,
- executionParams: {
- ...action.executionParams,
- featureName: selected,
- },
- })
- }
- fullWidth
- />
-
-
-
-
+ })
+ }
+ fullWidth
+ />
+
+
+
);
};
diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFilterItem.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFilterItem.tsx
index 6595271ce0..e0949f3c6a 100644
--- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFilterItem.tsx
+++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFilterItem.tsx
@@ -1,23 +1,20 @@
import { Badge, IconButton, Tooltip, styled } from '@mui/material';
-import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { ActionsFilterState } from './useProjectActionsForm';
-import { Fragment } from 'react';
import { Delete } from '@mui/icons-material';
import Input from 'component/common/Input/Input';
-import {
- BoxSeparator,
- StyledInnerBoxHeader,
- StyledRow,
- StyledInnerBox,
-} from './InnerContainerBox';
+import { ProjectActionsFormItem } from './ProjectActionsFormItem';
-const StyledInput = styled(Input)(() => ({
+const StyledInputContainer = styled('div')({
+ flex: 1,
+});
+
+const StyledInput = styled(Input)({
width: '100%',
-}));
+});
const StyledBadge = styled(Badge)(({ theme }) => ({
- color: 'primary',
- margin: theme.spacing(1),
+ margin: theme.spacing(0, 1),
+ fontSize: theme.fontSizes.mainHeader,
}));
export const ProjectActionsFilterItem = ({
@@ -32,47 +29,47 @@ export const ProjectActionsFilterItem = ({
onDelete: () => void;
}) => {
const { parameter, value } = filter;
+
+ const header = (
+ <>
+ Filter {index + 1}
+
+
+
+
+
+
+
+ >
+ );
+
return (
-
- 0}
- show={AND}
- />
-
-
- Filter {index + 1}
-
-
-
-
-
-
-
-
-
-
- stateChanged({
- ...filter,
- parameter: e.target.value,
- })
- }
- />
- =
-
- stateChanged({
- ...filter,
- value: e.target.value,
- })
- }
- />
-
-
-
+
+
+
+ stateChanged({
+ ...filter,
+ parameter: e.target.value,
+ })
+ }
+ />
+
+ =
+
+
+ stateChanged({
+ ...filter,
+ value: e.target.value,
+ })
+ }
+ />
+
+
);
};
diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsForm.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsForm.tsx
index 791eb60b5c..b5d1612b73 100644
--- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsForm.tsx
+++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsForm.tsx
@@ -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 Input from 'component/common/Input/Input';
-import { Badge } from 'component/common/Badge/Badge';
import { FormSwitch } from 'component/common/FormSwitch/FormSwitch';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import {
@@ -16,9 +15,9 @@ import { useMemo } from 'react';
import GeneralSelect, {} from 'component/common/GeneralSelect/GeneralSelect';
import { Add } from '@mui/icons-material';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
-import { StyledRow } from './InnerContainerBox';
import { ProjectActionsActionItem } from './ProjectActionsActionItem';
import { ProjectActionsFilterItem } from './ProjectActionsFilterItem';
+import { ProjectActionsFormStep } from './ProjectActionsFormStep';
const StyledServiceAccountAlert = styled(Alert)(({ theme }) => ({
marginBottom: theme.spacing(4),
@@ -44,27 +43,20 @@ const StyledInput = styled(Input)(() => ({
width: '100%',
}));
-const StyledBadge = styled(Badge)(({ theme }) => ({
- color: 'primary',
- margin: 'auto',
- marginBottom: theme.spacing(1.5),
-}));
-
-const StyledBox = styled(Box)(({ theme }) => ({
+const StyledSecondaryDescription = styled('p')(({ theme }) => ({
display: 'flex',
- flexDirection: 'column',
- backgroundColor: theme.palette.background.elevation1,
- marginTop: theme.spacing(2),
- padding: theme.spacing(2),
- borderRadius: theme.shape.borderRadiusMedium,
+ color: theme.palette.text.secondary,
+ fontSize: theme.fontSizes.smallBody,
}));
-const Step = ({ name, children }: any) => (
-
- {name}
- {children}
-
-);
+const StyledButtonContainer = styled('div')(({ theme }) => ({
+ marginTop: theme.spacing(2),
+}));
+
+const StyledDivider = styled(Divider)(({ theme }) => ({
+ margin: theme.spacing(3, 0),
+ marginBottom: theme.spacing(2),
+}));
interface IProjectActionsFormProps {
enabled: boolean;
@@ -101,6 +93,7 @@ export const ProjectActionsForm = ({
validateName,
validated,
}: IProjectActionsFormProps) => {
+ const projectId = useRequiredPathParam('projectId');
const { serviceAccounts, loading: serviceAccountsLoading } =
useServiceAccounts();
const { incomingWebhooks, loading: incomingWebhooksLoading } =
@@ -177,7 +170,7 @@ export const ProjectActionsForm = ({
}, [serviceAccountsLoading, serviceAccounts]);
const showErrors = validated && Object.values(errors).some(Boolean);
- const projectId = useRequiredPathParam('projectId');
+
return (
-
+
Create incoming webhooks from
@@ -235,9 +228,13 @@ export const ProjectActionsForm = ({
setSourceId(parseInt(v));
}}
/>
-
+
-
+
+
+ If no filters are defined then the action will be triggered
+ every time the incoming webhook is called.
+
{filters.map((filter, index) => (
))}
-
-
-
+
}
onClick={addFilter}
variant='outlined'
@@ -263,10 +257,10 @@ export const ProjectActionsForm = ({
>
Add filter
-
-
+
+
-
+
Create service accounts from
@@ -283,7 +277,7 @@ export const ProjectActionsForm = ({
setActorId(parseInt(v));
}}
/>
-
+
{actions.map((action, index) => (
))}
-
-
+
}
onClick={() => addAction(projectId)}
variant='outlined'
@@ -308,8 +300,8 @@ export const ProjectActionsForm = ({
>
Add action
-
-
+
+
({
+ 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 (
+
+ 0}
+ show={{separator}}
+ />
+
+ {header}
+ {children}
+
+
+ );
+};
diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFormStep.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFormStep.tsx
new file mode 100644
index 0000000000..f4139e185a
--- /dev/null
+++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/ProjectActionsFormStep.tsx
@@ -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) => (
+ <>
+ }
+ />
+
+ {name}
+ {children}
+
+ >
+);