mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-04 13:48:56 +02:00
feat: segments in pending CR screen (#4420)
This commit is contained in:
parent
e20e7df10f
commit
7a32eacecb
@ -29,6 +29,7 @@ const pendingChangeRequest = (featureName: string) =>
|
|||||||
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
|
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
|
||||||
},
|
},
|
||||||
createdAt: '2022-12-02T09:19:12.242Z',
|
createdAt: '2022-12-02T09:19:12.242Z',
|
||||||
|
segments: [],
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
name: featureName,
|
name: featureName,
|
||||||
|
@ -19,6 +19,7 @@ const changeRequestWithDefaultChange = (
|
|||||||
username: 'author',
|
username: 'author',
|
||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
},
|
},
|
||||||
|
segments: [],
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
name: 'Feature Toggle Name',
|
name: 'Feature Toggle Name',
|
||||||
|
@ -2,8 +2,10 @@ import React, { VFC } from 'react';
|
|||||||
import { Box, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import type { IChangeRequest } from '../changeRequest.types';
|
import type { IChangeRequest } from '../changeRequest.types';
|
||||||
import { FeatureToggleChanges } from './Changes/FeatureToggleChanges';
|
import { FeatureToggleChanges } from './Changes/FeatureToggleChanges';
|
||||||
import { Change } from './Changes/Change/Change';
|
import { FeatureChange } from './Changes/Change/FeatureChange';
|
||||||
import { ChangeActions } from './Changes/Change/ChangeActions';
|
import { ChangeActions } from './Changes/Change/ChangeActions';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { SegmentChange } from './Changes/Change/SegmentChange';
|
||||||
|
|
||||||
interface IChangeRequestProps {
|
interface IChangeRequestProps {
|
||||||
changeRequest: IChangeRequest;
|
changeRequest: IChangeRequest;
|
||||||
@ -18,6 +20,30 @@ export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest.segments.length > 0}
|
||||||
|
show={
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
You request changes for these segments:
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{changeRequest.segments?.map(segment => (
|
||||||
|
<SegmentChange
|
||||||
|
key={segment.payload.id}
|
||||||
|
segmentChange={segment}
|
||||||
|
onNavigate={onNavigate}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest.features.length > 0}
|
||||||
|
show={
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
You request changes for these feature toggles:
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
{changeRequest.features?.map(feature => (
|
{changeRequest.features?.map(feature => (
|
||||||
<FeatureToggleChanges
|
<FeatureToggleChanges
|
||||||
key={feature.name}
|
key={feature.name}
|
||||||
@ -27,7 +53,7 @@ export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
|||||||
conflict={feature.conflict}
|
conflict={feature.conflict}
|
||||||
>
|
>
|
||||||
{feature.changes.map((change, index) => (
|
{feature.changes.map((change, index) => (
|
||||||
<Change
|
<FeatureChange
|
||||||
key={index}
|
key={index}
|
||||||
discard={
|
discard={
|
||||||
<ChangeActions
|
<ChangeActions
|
||||||
@ -44,7 +70,7 @@ export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{feature.defaultChange ? (
|
{feature.defaultChange ? (
|
||||||
<Change
|
<FeatureChange
|
||||||
discard={
|
discard={
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { FC, useState } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
IChange,
|
IFeatureChange,
|
||||||
IChangeRequest,
|
IChangeRequest,
|
||||||
IChangeRequestAddStrategy,
|
IChangeRequestAddStrategy,
|
||||||
IChangeRequestUpdateStrategy,
|
IChangeRequestUpdateStrategy,
|
||||||
@ -26,7 +26,10 @@ import {
|
|||||||
import { Delete, Edit, MoreVert } from '@mui/icons-material';
|
import { Delete, Edit, MoreVert } from '@mui/icons-material';
|
||||||
import { EditChange } from './EditChange';
|
import { EditChange } from './EditChange';
|
||||||
|
|
||||||
const useShowActions = (changeRequest: IChangeRequest, change: IChange) => {
|
const useShowActions = (
|
||||||
|
changeRequest: IChangeRequest,
|
||||||
|
change: IFeatureChange
|
||||||
|
) => {
|
||||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(
|
const { isChangeRequestConfigured } = useChangeRequestsEnabled(
|
||||||
changeRequest.project
|
changeRequest.project
|
||||||
);
|
);
|
||||||
@ -57,7 +60,7 @@ const StyledPopover = styled(Popover)(({ theme }) => ({
|
|||||||
export const ChangeActions: FC<{
|
export const ChangeActions: FC<{
|
||||||
changeRequest: IChangeRequest;
|
changeRequest: IChangeRequest;
|
||||||
feature: string;
|
feature: string;
|
||||||
change: IChange;
|
change: IFeatureChange;
|
||||||
onRefetch?: () => void;
|
onRefetch?: () => void;
|
||||||
}> = ({ changeRequest, feature, change, onRefetch }) => {
|
}> = ({ changeRequest, feature, change, onRefetch }) => {
|
||||||
const { showDiscard, showEdit } = useShowActions(changeRequest, change);
|
const { showDiscard, showEdit } = useShowActions(changeRequest, change);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC, ReactNode } from 'react';
|
import { FC, ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
IChange,
|
IFeatureChange,
|
||||||
IChangeRequest,
|
IChangeRequest,
|
||||||
IChangeRequestFeature,
|
IChangeRequestFeature,
|
||||||
} from '../../../changeRequest.types';
|
} from '../../../changeRequest.types';
|
||||||
@ -54,11 +54,11 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Change: FC<{
|
export const FeatureChange: FC<{
|
||||||
discard: ReactNode;
|
discard: ReactNode;
|
||||||
index: number;
|
index: number;
|
||||||
changeRequest: IChangeRequest;
|
changeRequest: IChangeRequest;
|
||||||
change: IChange;
|
change: IFeatureChange;
|
||||||
feature: IChangeRequestFeature;
|
feature: IChangeRequestFeature;
|
||||||
}> = ({ index, change, feature, changeRequest, discard }) => {
|
}> = ({ index, change, feature, changeRequest, discard }) => {
|
||||||
const lastIndex = feature.defaultChange
|
const lastIndex = feature.defaultChange
|
||||||
@ -82,6 +82,7 @@ export const Change: FC<{
|
|||||||
</StyledAlert>
|
</StyledAlert>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box sx={theme => ({ padding: theme.spacing(3) })}>
|
<Box sx={theme => ({ padding: theme.spacing(3) })}>
|
||||||
{change.action === 'updateEnabled' && (
|
{change.action === 'updateEnabled' && (
|
||||||
<ToggleStatusChange
|
<ToggleStatusChange
|
||||||
@ -89,6 +90,7 @@ export const Change: FC<{
|
|||||||
discard={discard}
|
discard={discard}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{change.action === 'addStrategy' ||
|
{change.action === 'addStrategy' ||
|
||||||
change.action === 'deleteStrategy' ||
|
change.action === 'deleteStrategy' ||
|
||||||
change.action === 'updateStrategy' ? (
|
change.action === 'updateStrategy' ? (
|
@ -0,0 +1,64 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
|
import { Box, Card, Typography, Link } from '@mui/material';
|
||||||
|
import { ISegmentChange } from '../../../changeRequest.types';
|
||||||
|
import { SegmentChangeDetails } from './SegmentChangeDetails';
|
||||||
|
|
||||||
|
interface ISegmentChangeProps {
|
||||||
|
segmentChange: ISegmentChange;
|
||||||
|
onNavigate?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SegmentChange: FC<ISegmentChangeProps> = ({
|
||||||
|
segmentChange,
|
||||||
|
onNavigate,
|
||||||
|
}) => (
|
||||||
|
<Card
|
||||||
|
elevation={0}
|
||||||
|
sx={theme => ({
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
overflow: 'hidden',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={theme => ({
|
||||||
|
backgroundColor: theme.palette.neutral.light,
|
||||||
|
borderRadius: theme =>
|
||||||
|
`${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px 0 0`,
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: theme => theme.palette.divider,
|
||||||
|
borderBottom: 'none',
|
||||||
|
overflow: 'hidden',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
pt: 2,
|
||||||
|
pb: 2,
|
||||||
|
px: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography>Segment name: </Typography>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
component={RouterLink}
|
||||||
|
to={`/segments/${segmentChange.payload.id}`}
|
||||||
|
color="primary"
|
||||||
|
underline="hover"
|
||||||
|
sx={{
|
||||||
|
marginLeft: 1,
|
||||||
|
'& :hover': {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={onNavigate}
|
||||||
|
>
|
||||||
|
<strong>{segmentChange.payload.name}</strong>
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<SegmentChangeDetails change={segmentChange} />
|
||||||
|
</Card>
|
||||||
|
);
|
@ -0,0 +1,89 @@
|
|||||||
|
import { VFC, FC, ReactNode } from 'react';
|
||||||
|
import { Box, styled, Typography } from '@mui/material';
|
||||||
|
import {
|
||||||
|
IChangeRequestDeleteSegment,
|
||||||
|
IChangeRequestUpdateSegment,
|
||||||
|
} from 'component/changeRequest/changeRequest.types';
|
||||||
|
import { useSegment } from 'hooks/api/getters/useSegment/useSegment';
|
||||||
|
import { SegmentDiff, SegmentTooltipLink } from '../../SegmentTooltipLink';
|
||||||
|
|
||||||
|
const ChangeItemCreateEditWrapper = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'auto 40px',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '100%',
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ChangeItemWrapper = styled(Box)({
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
|
const ChangeItemInfo: FC = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '150px auto',
|
||||||
|
gridAutoFlow: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexGrow: 1,
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const SegmentContainer = styled(Box)(({ theme }) => ({
|
||||||
|
borderLeft: '1px solid',
|
||||||
|
borderRight: '1px solid',
|
||||||
|
borderTop: '1px solid',
|
||||||
|
borderBottom: '1px solid',
|
||||||
|
borderColor: theme.palette.divider,
|
||||||
|
borderTopColor: theme.palette.divider,
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const SegmentChangeDetails: VFC<{
|
||||||
|
discard?: ReactNode;
|
||||||
|
change: IChangeRequestUpdateSegment | IChangeRequestDeleteSegment;
|
||||||
|
}> = ({ discard, change }) => {
|
||||||
|
const { segment: currentSegment } = useSegment(change.payload.id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SegmentContainer>
|
||||||
|
{change.action === 'deleteSegment' && (
|
||||||
|
<ChangeItemWrapper>
|
||||||
|
<ChangeItemInfo>
|
||||||
|
<Typography
|
||||||
|
sx={theme => ({
|
||||||
|
color: theme.palette.error.main,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
- Deleting segment:
|
||||||
|
</Typography>
|
||||||
|
<SegmentTooltipLink change={change}>
|
||||||
|
<SegmentDiff
|
||||||
|
change={change}
|
||||||
|
currentSegment={currentSegment}
|
||||||
|
/>
|
||||||
|
</SegmentTooltipLink>
|
||||||
|
</ChangeItemInfo>
|
||||||
|
<div>{discard}</div>
|
||||||
|
</ChangeItemWrapper>
|
||||||
|
)}
|
||||||
|
{change.action === 'updateSegment' && (
|
||||||
|
<>
|
||||||
|
<ChangeItemCreateEditWrapper>
|
||||||
|
<ChangeItemInfo>
|
||||||
|
<Typography>Editing segment:</Typography>
|
||||||
|
<SegmentTooltipLink change={change}>
|
||||||
|
<SegmentDiff
|
||||||
|
change={change}
|
||||||
|
currentSegment={currentSegment}
|
||||||
|
/>
|
||||||
|
</SegmentTooltipLink>
|
||||||
|
</ChangeItemInfo>
|
||||||
|
<div>{discard}</div>
|
||||||
|
</ChangeItemCreateEditWrapper>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</SegmentContainer>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,79 @@
|
|||||||
|
import {
|
||||||
|
IChangeRequestDeleteSegment,
|
||||||
|
IChangeRequestUpdateSegment,
|
||||||
|
} from 'component/changeRequest/changeRequest.types';
|
||||||
|
import { FC } from 'react';
|
||||||
|
import { formatStrategyName } from 'utils/strategyNames';
|
||||||
|
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||||
|
import omit from 'lodash.omit';
|
||||||
|
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
||||||
|
import { Typography, styled } from '@mui/material';
|
||||||
|
import { textTruncated } from 'themes/themeStyles';
|
||||||
|
import { ISegment } from 'interfaces/segment';
|
||||||
|
|
||||||
|
const StyledCodeSection = styled('div')(({ theme }) => ({
|
||||||
|
overflowX: 'auto',
|
||||||
|
'& code': {
|
||||||
|
wordWrap: 'break-word',
|
||||||
|
whiteSpace: 'pre-wrap',
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
lineHeight: 1.5,
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const SegmentDiff: FC<{
|
||||||
|
change: IChangeRequestUpdateSegment | IChangeRequestDeleteSegment;
|
||||||
|
currentSegment?: ISegment;
|
||||||
|
}> = ({ change, currentSegment }) => {
|
||||||
|
const changeRequestStrategy =
|
||||||
|
change.action === 'deleteSegment' ? undefined : change.payload;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledCodeSection>
|
||||||
|
<EventDiff
|
||||||
|
entry={{
|
||||||
|
preData: omit(currentSegment, 'sortOrder'),
|
||||||
|
data: changeRequestStrategy,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StyledCodeSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
interface IStrategyTooltipLinkProps {
|
||||||
|
change: IChangeRequestUpdateSegment | IChangeRequestDeleteSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledContainer: FC = styled('div')(({ theme }) => ({
|
||||||
|
display: 'grid',
|
||||||
|
gridAutoFlow: 'column',
|
||||||
|
gridTemplateColumns: 'auto 1fr',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
alignItems: 'center',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Truncated = styled('div')(() => ({
|
||||||
|
...textTruncated,
|
||||||
|
maxWidth: 500,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const SegmentTooltipLink: FC<IStrategyTooltipLinkProps> = ({
|
||||||
|
change,
|
||||||
|
children,
|
||||||
|
}) => (
|
||||||
|
<StyledContainer>
|
||||||
|
<Truncated>
|
||||||
|
<TooltipLink
|
||||||
|
tooltip={children}
|
||||||
|
tooltipProps={{
|
||||||
|
maxWidth: 500,
|
||||||
|
maxHeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography component="span">
|
||||||
|
{formatStrategyName(change.payload.name)}
|
||||||
|
</Typography>
|
||||||
|
</TooltipLink>
|
||||||
|
</Truncated>
|
||||||
|
</StyledContainer>
|
||||||
|
);
|
@ -112,11 +112,7 @@ export const EnvironmentChangeRequest: FC<{
|
|||||||
</ChangeRequestTitle>
|
</ChangeRequestTitle>
|
||||||
</ChangeRequestHeader>
|
</ChangeRequestHeader>
|
||||||
<ChangeRequestContent>
|
<ChangeRequestContent>
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
You request changes for these feature toggles:
|
|
||||||
</Typography>
|
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={environmentChangeRequest?.state === 'Draft'}
|
condition={environmentChangeRequest?.state === 'Draft'}
|
||||||
show={
|
show={
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React, { FC, useState } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { ChangeRequestTitle } from './ChangeRequestTitle';
|
import { ChangeRequestTitle } from './ChangeRequestTitle';
|
||||||
import { ChangeRequestState } from '../../changeRequest.types';
|
import { ChangeRequestState } from 'component/changeRequest/changeRequest.types';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||||
import { render } from 'utils/testRenderer';
|
import { render } from 'utils/testRenderer';
|
||||||
import { UIProviderContainer } from '../../../providers/UIProvider/UIProviderContainer';
|
import { UIProviderContainer } from 'component/providers/UIProvider/UIProviderContainer';
|
||||||
|
|
||||||
const changeRequest = {
|
const changeRequest = {
|
||||||
id: 3,
|
id: 3,
|
||||||
@ -19,6 +19,7 @@ const changeRequest = {
|
|||||||
features: [],
|
features: [],
|
||||||
approvals: [],
|
approvals: [],
|
||||||
comments: [],
|
comments: [],
|
||||||
|
segments: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const server = testServerSetup();
|
const server = testServerSetup();
|
||||||
|
@ -13,6 +13,7 @@ export interface IChangeRequest {
|
|||||||
createdBy: Pick<IUser, 'id' | 'username' | 'imageUrl'>;
|
createdBy: Pick<IUser, 'id' | 'username' | 'imageUrl'>;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
features: IChangeRequestFeature[];
|
features: IChangeRequestFeature[];
|
||||||
|
segments: ISegmentChange[];
|
||||||
approvals: IChangeRequestApproval[];
|
approvals: IChangeRequestApproval[];
|
||||||
comments: IChangeRequestComment[];
|
comments: IChangeRequestComment[];
|
||||||
conflict?: string;
|
conflict?: string;
|
||||||
@ -28,7 +29,14 @@ export interface IChangeRequestEnvironmentConfig {
|
|||||||
export interface IChangeRequestFeature {
|
export interface IChangeRequestFeature {
|
||||||
name: string;
|
name: string;
|
||||||
conflict?: string;
|
conflict?: string;
|
||||||
changes: IChange[];
|
changes: IFeatureChange[];
|
||||||
|
defaultChange?: IChangeRequestAddStrategy | IChangeRequestEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IChangeRequestSegment {
|
||||||
|
name: string;
|
||||||
|
conflict?: string;
|
||||||
|
changes: IFeatureChange[];
|
||||||
defaultChange?: IChangeRequestAddStrategy | IChangeRequestEnabled;
|
defaultChange?: IChangeRequestAddStrategy | IChangeRequestEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +52,7 @@ export interface IChangeRequestComment {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestBase {
|
export interface IChangeRequestChangeBase {
|
||||||
id: number;
|
id: number;
|
||||||
action: ChangeRequestAction;
|
action: ChangeRequestAction;
|
||||||
payload: ChangeRequestPayload;
|
payload: ChangeRequestPayload;
|
||||||
@ -66,39 +74,63 @@ type ChangeRequestPayload =
|
|||||||
| ChangeRequestEditStrategy
|
| ChangeRequestEditStrategy
|
||||||
| ChangeRequestDeleteStrategy
|
| ChangeRequestDeleteStrategy
|
||||||
| ChangeRequestVariantPatch
|
| ChangeRequestVariantPatch
|
||||||
|
| IChangeRequestUpdateSegment
|
||||||
|
| IChangeRequestDeleteSegment
|
||||||
| SetStrategySortOrderSchema;
|
| SetStrategySortOrderSchema;
|
||||||
|
|
||||||
export interface IChangeRequestAddStrategy extends IChangeRequestBase {
|
export interface IChangeRequestAddStrategy extends IChangeRequestChangeBase {
|
||||||
action: 'addStrategy';
|
action: 'addStrategy';
|
||||||
payload: ChangeRequestAddStrategy;
|
payload: ChangeRequestAddStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestDeleteStrategy extends IChangeRequestBase {
|
export interface IChangeRequestDeleteStrategy extends IChangeRequestChangeBase {
|
||||||
action: 'deleteStrategy';
|
action: 'deleteStrategy';
|
||||||
payload: ChangeRequestDeleteStrategy;
|
payload: ChangeRequestDeleteStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestUpdateStrategy extends IChangeRequestBase {
|
export interface IChangeRequestUpdateStrategy extends IChangeRequestChangeBase {
|
||||||
action: 'updateStrategy';
|
action: 'updateStrategy';
|
||||||
payload: ChangeRequestEditStrategy;
|
payload: ChangeRequestEditStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestEnabled extends IChangeRequestBase {
|
export interface IChangeRequestEnabled extends IChangeRequestChangeBase {
|
||||||
action: 'updateEnabled';
|
action: 'updateEnabled';
|
||||||
payload: ChangeRequestEnabled;
|
payload: ChangeRequestEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestPatchVariant extends IChangeRequestBase {
|
export interface IChangeRequestPatchVariant extends IChangeRequestChangeBase {
|
||||||
action: 'patchVariant';
|
action: 'patchVariant';
|
||||||
payload: ChangeRequestVariantPatch;
|
payload: ChangeRequestVariantPatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChangeRequestReorderStrategy extends IChangeRequestBase {
|
export interface IChangeRequestReorderStrategy
|
||||||
|
extends IChangeRequestChangeBase {
|
||||||
action: 'reorderStrategy';
|
action: 'reorderStrategy';
|
||||||
payload: SetStrategySortOrderSchema;
|
payload: SetStrategySortOrderSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IChange =
|
export interface IChangeRequestUpdateSegment {
|
||||||
|
action: 'updateSegment';
|
||||||
|
payload: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
project?: string;
|
||||||
|
constraints: IFeatureStrategy['constraints'];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IChangeRequestDeleteSegment {
|
||||||
|
action: 'deleteSegment';
|
||||||
|
payload: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IChange = IFeatureChange | ISegmentChange;
|
||||||
|
|
||||||
|
export type IFeatureChange =
|
||||||
| IChangeRequestAddStrategy
|
| IChangeRequestAddStrategy
|
||||||
| IChangeRequestDeleteStrategy
|
| IChangeRequestDeleteStrategy
|
||||||
| IChangeRequestUpdateStrategy
|
| IChangeRequestUpdateStrategy
|
||||||
@ -106,6 +138,10 @@ export type IChange =
|
|||||||
| IChangeRequestPatchVariant
|
| IChangeRequestPatchVariant
|
||||||
| IChangeRequestReorderStrategy;
|
| IChangeRequestReorderStrategy;
|
||||||
|
|
||||||
|
export type ISegmentChange =
|
||||||
|
| IChangeRequestUpdateSegment
|
||||||
|
| IChangeRequestDeleteSegment;
|
||||||
|
|
||||||
type ChangeRequestVariantPatch = {
|
type ChangeRequestVariantPatch = {
|
||||||
variants: IFeatureVariant[];
|
variants: IFeatureVariant[];
|
||||||
};
|
};
|
||||||
@ -132,4 +168,6 @@ export type ChangeRequestAction =
|
|||||||
| 'updateStrategy'
|
| 'updateStrategy'
|
||||||
| 'deleteStrategy'
|
| 'deleteStrategy'
|
||||||
| 'patchVariant'
|
| 'patchVariant'
|
||||||
| 'reorderStrategy';
|
| 'reorderStrategy'
|
||||||
|
| 'updateSegment'
|
||||||
|
| 'deleteSegment';
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { IChangeRequest } from './changeRequest.types';
|
import { IChangeRequest } from './changeRequest.types';
|
||||||
|
|
||||||
export const changesCount = (changeRequest: IChangeRequest) =>
|
export const changesCount = (changeRequest: IChangeRequest) =>
|
||||||
changeRequest.features.flatMap(feature => feature.changes).length;
|
changeRequest.features.flatMap(feature => feature.changes).length +
|
||||||
|
changeRequest.segments.length;
|
||||||
|
@ -7,7 +7,7 @@ import { IFeatureStrategy } from 'interfaces/strategy';
|
|||||||
import { StrategyItem } from './StrategyItem/StrategyItem';
|
import { StrategyItem } from './StrategyItem/StrategyItem';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
import { IChange } from 'component/changeRequest/changeRequest.types';
|
import { IFeatureChange } from 'component/changeRequest/changeRequest.types';
|
||||||
import { useStrategyChangeFromRequest } from './StrategyItem/useStrategyChangeFromRequest';
|
import { useStrategyChangeFromRequest } from './StrategyItem/useStrategyChangeFromRequest';
|
||||||
|
|
||||||
interface IStrategyDraggableItemProps {
|
interface IStrategyDraggableItemProps {
|
||||||
@ -74,7 +74,7 @@ export const StrategyDraggableItem = ({
|
|||||||
const ChangeRequestStatusBadge = ({
|
const ChangeRequestStatusBadge = ({
|
||||||
change,
|
change,
|
||||||
}: {
|
}: {
|
||||||
change: IChange | undefined;
|
change: IFeatureChange | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
|
Loading…
Reference in New Issue
Block a user