mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-18 01:18:23 +02:00
hide discard for nonauthors (#2634)
This commit is contained in:
parent
1be2483e6a
commit
2107834768
@ -1,30 +1,9 @@
|
|||||||
import React, { FC, VFC } from 'react';
|
import React, { VFC } from 'react';
|
||||||
import { Alert, Box, styled } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { ChangeRequestFeatureToggleChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ChangeRequestFeatureToggleChange';
|
import type { IChangeRequest } from '../changeRequest.types';
|
||||||
import { objectId } from 'utils/objectId';
|
import { FeatureToggleChanges } from './Changes/FeatureToggleChanges';
|
||||||
import { ToggleStatusChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ToggleStatusChange';
|
import { Change } from './Changes/Change/Change';
|
||||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
import { DiscardContainer } from './Changes/Change/Discard';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
|
||||||
import useToast from 'hooks/useToast';
|
|
||||||
import type {
|
|
||||||
IChange,
|
|
||||||
IChangeRequest,
|
|
||||||
IChangeRequestFeature,
|
|
||||||
} from '../changeRequest.types';
|
|
||||||
import { hasNameField } from '../changeRequest.types';
|
|
||||||
import {
|
|
||||||
Discard,
|
|
||||||
StrategyAddedChange,
|
|
||||||
StrategyDeletedChange,
|
|
||||||
StrategyEditedChange,
|
|
||||||
} from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/StrategyChange';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
|
||||||
import { StrategyExecution } from '../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
|
|
||||||
import {
|
|
||||||
CodeSnippetPopover,
|
|
||||||
PopoverDiff,
|
|
||||||
} from './CodeSnippetPopover/CodeSnippetPopover';
|
|
||||||
|
|
||||||
interface IChangeRequestProps {
|
interface IChangeRequestProps {
|
||||||
changeRequest: IChangeRequest;
|
changeRequest: IChangeRequest;
|
||||||
@ -32,190 +11,15 @@ interface IChangeRequestProps {
|
|||||||
onNavigate?: () => void;
|
onNavigate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledSingleChangeBox = styled(Box, {
|
|
||||||
shouldForwardProp: (prop: string) => !prop.startsWith('$'),
|
|
||||||
})<{
|
|
||||||
$hasConflict: boolean;
|
|
||||||
$isAfterWarning: boolean;
|
|
||||||
$isLast: boolean;
|
|
||||||
$isInConflictFeature: boolean;
|
|
||||||
}>(
|
|
||||||
({
|
|
||||||
theme,
|
|
||||||
$hasConflict,
|
|
||||||
$isInConflictFeature,
|
|
||||||
$isAfterWarning,
|
|
||||||
$isLast,
|
|
||||||
}) => ({
|
|
||||||
borderLeft: '1px solid',
|
|
||||||
borderRight: '1px solid',
|
|
||||||
borderTop: '1px solid',
|
|
||||||
borderBottom: $isLast ? '1px solid' : 'none',
|
|
||||||
borderRadius: $isLast
|
|
||||||
? `0 0
|
|
||||||
${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px`
|
|
||||||
: 0,
|
|
||||||
borderColor:
|
|
||||||
$hasConflict || $isInConflictFeature
|
|
||||||
? theme.palette.warning.border
|
|
||||||
: theme.palette.dividerAlternative,
|
|
||||||
borderTopColor:
|
|
||||||
($hasConflict || $isAfterWarning) && !$isInConflictFeature
|
|
||||||
? theme.palette.warning.border
|
|
||||||
: theme.palette.dividerAlternative,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const StyledAlert = styled(Alert)(({ theme }) => ({
|
|
||||||
borderRadius: 0,
|
|
||||||
padding: theme.spacing(0, 2),
|
|
||||||
'&.MuiAlert-standardWarning': {
|
|
||||||
borderStyle: 'none none solid none',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const Change: FC<{
|
|
||||||
onDiscard: () => Promise<void>;
|
|
||||||
index: number;
|
|
||||||
changeRequest: IChangeRequest;
|
|
||||||
change: IChange;
|
|
||||||
feature: IChangeRequestFeature;
|
|
||||||
}> = ({ index, change, feature, changeRequest, onDiscard }) => {
|
|
||||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(
|
|
||||||
changeRequest.project
|
|
||||||
);
|
|
||||||
const allowChangeRequestActions = isChangeRequestConfigured(
|
|
||||||
changeRequest.environment
|
|
||||||
);
|
|
||||||
|
|
||||||
const showDiscard =
|
|
||||||
allowChangeRequestActions &&
|
|
||||||
!['Cancelled', 'Applied'].includes(changeRequest.state) &&
|
|
||||||
changeRequest.features.flatMap(feature => feature.changes).length > 1;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledSingleChangeBox
|
|
||||||
key={objectId(change)}
|
|
||||||
$hasConflict={Boolean(change.conflict)}
|
|
||||||
$isInConflictFeature={Boolean(feature.conflict)}
|
|
||||||
$isAfterWarning={Boolean(feature.changes[index - 1]?.conflict)}
|
|
||||||
$isLast={index + 1 === feature.changes.length}
|
|
||||||
>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(change.conflict) && !feature.conflict}
|
|
||||||
show={
|
|
||||||
<StyledAlert severity="warning">
|
|
||||||
<strong>Conflict!</strong> This change can’t be applied.{' '}
|
|
||||||
{change.conflict}.
|
|
||||||
</StyledAlert>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Box sx={{ p: 2 }}>
|
|
||||||
{change.action === 'updateEnabled' && (
|
|
||||||
<ToggleStatusChange
|
|
||||||
enabled={change.payload.enabled}
|
|
||||||
discard={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={showDiscard}
|
|
||||||
show={<Discard onDiscard={onDiscard} />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{change.action === 'addStrategy' && (
|
|
||||||
<>
|
|
||||||
<StrategyAddedChange
|
|
||||||
discard={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={showDiscard}
|
|
||||||
show={<Discard onDiscard={onDiscard} />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<CodeSnippetPopover change={change}>
|
|
||||||
<PopoverDiff
|
|
||||||
change={change}
|
|
||||||
feature={feature.name}
|
|
||||||
environmentName={changeRequest.environment}
|
|
||||||
project={changeRequest.project}
|
|
||||||
/>
|
|
||||||
</CodeSnippetPopover>
|
|
||||||
</StrategyAddedChange>
|
|
||||||
<StrategyExecution strategy={change.payload} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{change.action === 'deleteStrategy' && (
|
|
||||||
<StrategyDeletedChange
|
|
||||||
discard={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={showDiscard}
|
|
||||||
show={<Discard onDiscard={onDiscard} />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{hasNameField(change.payload) && (
|
|
||||||
<CodeSnippetPopover change={change}>
|
|
||||||
<PopoverDiff
|
|
||||||
change={change}
|
|
||||||
feature={feature.name}
|
|
||||||
environmentName={changeRequest.environment}
|
|
||||||
project={changeRequest.project}
|
|
||||||
/>
|
|
||||||
</CodeSnippetPopover>
|
|
||||||
)}
|
|
||||||
</StrategyDeletedChange>
|
|
||||||
)}
|
|
||||||
{change.action === 'updateStrategy' && (
|
|
||||||
<>
|
|
||||||
<StrategyEditedChange
|
|
||||||
discard={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={showDiscard}
|
|
||||||
show={<Discard onDiscard={onDiscard} />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<CodeSnippetPopover change={change}>
|
|
||||||
<PopoverDiff
|
|
||||||
change={change}
|
|
||||||
feature={feature.name}
|
|
||||||
environmentName={changeRequest.environment}
|
|
||||||
project={changeRequest.project}
|
|
||||||
/>
|
|
||||||
</CodeSnippetPopover>
|
|
||||||
</StrategyEditedChange>
|
|
||||||
<StrategyExecution strategy={change.payload} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</StyledSingleChangeBox>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
||||||
changeRequest,
|
changeRequest,
|
||||||
onRefetch,
|
onRefetch,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
}) => {
|
}) => {
|
||||||
const { discardChange } = useChangeRequestApi();
|
|
||||||
const { setToastData, setToastApiError } = useToast();
|
|
||||||
const onDiscard = (id: number) => async () => {
|
|
||||||
try {
|
|
||||||
await discardChange(changeRequest.project, changeRequest.id, id);
|
|
||||||
setToastData({
|
|
||||||
title: 'Change discarded from change request draft.',
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
onRefetch?.();
|
|
||||||
} catch (error: unknown) {
|
|
||||||
setToastApiError(formatUnknownError(error));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{changeRequest.features?.map(feature => (
|
{changeRequest.features?.map(feature => (
|
||||||
<ChangeRequestFeatureToggleChange
|
<FeatureToggleChanges
|
||||||
key={feature.name}
|
key={feature.name}
|
||||||
featureName={feature.name}
|
featureName={feature.name}
|
||||||
projectId={changeRequest.project}
|
projectId={changeRequest.project}
|
||||||
@ -225,14 +29,20 @@ export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
|||||||
{feature.changes.map((change, index) => (
|
{feature.changes.map((change, index) => (
|
||||||
<Change
|
<Change
|
||||||
key={index}
|
key={index}
|
||||||
onDiscard={onDiscard(change.id)}
|
discard={
|
||||||
|
<DiscardContainer
|
||||||
|
changeRequest={changeRequest}
|
||||||
|
changeId={change.id}
|
||||||
|
onPostDiscard={onRefetch}
|
||||||
|
/>
|
||||||
|
}
|
||||||
index={index}
|
index={index}
|
||||||
changeRequest={changeRequest}
|
changeRequest={changeRequest}
|
||||||
change={change}
|
change={change}
|
||||||
feature={feature}
|
feature={feature}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ChangeRequestFeatureToggleChange>
|
</FeatureToggleChanges>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
import React, { FC, ReactNode } from 'react';
|
||||||
|
import {
|
||||||
|
hasNameField,
|
||||||
|
IChange,
|
||||||
|
IChangeRequest,
|
||||||
|
IChangeRequestFeature,
|
||||||
|
} from '../../../changeRequest.types';
|
||||||
|
import { objectId } from 'utils/objectId';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { Alert, Box, styled } from '@mui/material';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CodeSnippetPopover,
|
||||||
|
PopoverDiff,
|
||||||
|
} from '../../CodeSnippetPopover/CodeSnippetPopover';
|
||||||
|
import { StrategyExecution } from '../../../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
|
||||||
|
import { ToggleStatusChange } from './ToggleStatusChange';
|
||||||
|
import {
|
||||||
|
StrategyAddedChange,
|
||||||
|
StrategyDeletedChange,
|
||||||
|
StrategyEditedChange,
|
||||||
|
} from './StrategyChange';
|
||||||
|
|
||||||
|
const StyledSingleChangeBox = styled(Box, {
|
||||||
|
shouldForwardProp: (prop: string) => !prop.startsWith('$'),
|
||||||
|
})<{
|
||||||
|
$hasConflict: boolean;
|
||||||
|
$isAfterWarning: boolean;
|
||||||
|
$isLast: boolean;
|
||||||
|
$isInConflictFeature: boolean;
|
||||||
|
}>(
|
||||||
|
({
|
||||||
|
theme,
|
||||||
|
$hasConflict,
|
||||||
|
$isInConflictFeature,
|
||||||
|
$isAfterWarning,
|
||||||
|
$isLast,
|
||||||
|
}) => ({
|
||||||
|
borderLeft: '1px solid',
|
||||||
|
borderRight: '1px solid',
|
||||||
|
borderTop: '1px solid',
|
||||||
|
borderBottom: $isLast ? '1px solid' : 'none',
|
||||||
|
borderRadius: $isLast
|
||||||
|
? `0 0
|
||||||
|
${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px`
|
||||||
|
: 0,
|
||||||
|
borderColor:
|
||||||
|
$hasConflict || $isInConflictFeature
|
||||||
|
? theme.palette.warning.border
|
||||||
|
: theme.palette.dividerAlternative,
|
||||||
|
borderTopColor:
|
||||||
|
($hasConflict || $isAfterWarning) && !$isInConflictFeature
|
||||||
|
? theme.palette.warning.border
|
||||||
|
: theme.palette.dividerAlternative,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const StyledAlert = styled(Alert)(({ theme }) => ({
|
||||||
|
borderRadius: 0,
|
||||||
|
padding: theme.spacing(0, 2),
|
||||||
|
'&.MuiAlert-standardWarning': {
|
||||||
|
borderStyle: 'none none solid none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const Change: FC<{
|
||||||
|
discard: ReactNode;
|
||||||
|
index: number;
|
||||||
|
changeRequest: IChangeRequest;
|
||||||
|
change: IChange;
|
||||||
|
feature: IChangeRequestFeature;
|
||||||
|
}> = ({ index, change, feature, changeRequest, discard }) => {
|
||||||
|
return (
|
||||||
|
<StyledSingleChangeBox
|
||||||
|
key={objectId(change)}
|
||||||
|
$hasConflict={Boolean(change.conflict)}
|
||||||
|
$isInConflictFeature={Boolean(feature.conflict)}
|
||||||
|
$isAfterWarning={Boolean(feature.changes[index - 1]?.conflict)}
|
||||||
|
$isLast={index + 1 === feature.changes.length}
|
||||||
|
>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(change.conflict) && !feature.conflict}
|
||||||
|
show={
|
||||||
|
<StyledAlert severity="warning">
|
||||||
|
<strong>Conflict!</strong> This change can’t be applied.{' '}
|
||||||
|
{change.conflict}.
|
||||||
|
</StyledAlert>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Box sx={{ p: 2 }}>
|
||||||
|
{change.action === 'updateEnabled' && (
|
||||||
|
<ToggleStatusChange
|
||||||
|
enabled={change.payload.enabled}
|
||||||
|
discard={discard}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{change.action === 'addStrategy' && (
|
||||||
|
<>
|
||||||
|
<StrategyAddedChange discard={discard}>
|
||||||
|
<CodeSnippetPopover change={change}>
|
||||||
|
<PopoverDiff
|
||||||
|
change={change}
|
||||||
|
feature={feature.name}
|
||||||
|
environmentName={changeRequest.environment}
|
||||||
|
project={changeRequest.project}
|
||||||
|
/>
|
||||||
|
</CodeSnippetPopover>
|
||||||
|
</StrategyAddedChange>
|
||||||
|
<StrategyExecution strategy={change.payload} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{change.action === 'deleteStrategy' && (
|
||||||
|
<StrategyDeletedChange discard={discard}>
|
||||||
|
{hasNameField(change.payload) && (
|
||||||
|
<CodeSnippetPopover change={change}>
|
||||||
|
<PopoverDiff
|
||||||
|
change={change}
|
||||||
|
feature={feature.name}
|
||||||
|
environmentName={changeRequest.environment}
|
||||||
|
project={changeRequest.project}
|
||||||
|
/>
|
||||||
|
</CodeSnippetPopover>
|
||||||
|
)}
|
||||||
|
</StrategyDeletedChange>
|
||||||
|
)}
|
||||||
|
{change.action === 'updateStrategy' && (
|
||||||
|
<>
|
||||||
|
<StrategyEditedChange discard={discard}>
|
||||||
|
<CodeSnippetPopover change={change}>
|
||||||
|
<PopoverDiff
|
||||||
|
change={change}
|
||||||
|
feature={feature.name}
|
||||||
|
environmentName={changeRequest.environment}
|
||||||
|
project={changeRequest.project}
|
||||||
|
/>
|
||||||
|
</CodeSnippetPopover>
|
||||||
|
</StrategyEditedChange>
|
||||||
|
<StrategyExecution strategy={change.payload} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</StyledSingleChangeBox>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,74 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
import { IChangeRequest } from '../../../changeRequest.types';
|
||||||
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
|
import useToast from 'hooks/useToast';
|
||||||
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
|
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
|
||||||
|
import { changesCount } from '../../../changesCount';
|
||||||
|
import { Box, Link, styled } from '@mui/material';
|
||||||
|
|
||||||
|
const useShowDiscard = (changeRequest: IChangeRequest) => {
|
||||||
|
const { isChangeRequestConfigured } = useChangeRequestsEnabled(
|
||||||
|
changeRequest.project
|
||||||
|
);
|
||||||
|
const allowChangeRequestActions = isChangeRequestConfigured(
|
||||||
|
changeRequest.environment
|
||||||
|
);
|
||||||
|
const isPending = !['Cancelled', 'Applied'].includes(changeRequest.state);
|
||||||
|
|
||||||
|
const { user } = useAuthUser();
|
||||||
|
const isAuthor = user?.id === changeRequest.createdBy.id;
|
||||||
|
|
||||||
|
const showDiscard =
|
||||||
|
allowChangeRequestActions &&
|
||||||
|
isPending &&
|
||||||
|
isAuthor &&
|
||||||
|
changesCount(changeRequest) > 1;
|
||||||
|
|
||||||
|
return showDiscard;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledLink = styled(Link)(() => ({
|
||||||
|
textDecoration: 'none',
|
||||||
|
'&:hover, &:focus': {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Discard: FC<{ onDiscard: () => void }> = ({ onDiscard }) => (
|
||||||
|
<Box>
|
||||||
|
<StyledLink onClick={onDiscard}>Discard</StyledLink>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DiscardContainer: FC<{
|
||||||
|
changeRequest: IChangeRequest;
|
||||||
|
changeId: number;
|
||||||
|
onPostDiscard?: () => void;
|
||||||
|
}> = ({ changeRequest, changeId, onPostDiscard }) => {
|
||||||
|
const showDiscard = useShowDiscard(changeRequest);
|
||||||
|
const { discardChange } = useChangeRequestApi();
|
||||||
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
|
const onDiscard = (id: number) => async () => {
|
||||||
|
try {
|
||||||
|
await discardChange(changeRequest.project, changeRequest.id, id);
|
||||||
|
setToastData({
|
||||||
|
title: 'Change discarded from change request draft.',
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
onPostDiscard?.();
|
||||||
|
} catch (error: unknown) {
|
||||||
|
setToastApiError(formatUnknownError(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={showDiscard}
|
||||||
|
show={<Discard onDiscard={onDiscard(changeId)} />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -1,10 +1,6 @@
|
|||||||
import { Box, Link, styled, Typography } from '@mui/material';
|
import { Box, Link, styled, Typography } from '@mui/material';
|
||||||
import { FC, ReactNode } from 'react';
|
import { FC, ReactNode } from 'react';
|
||||||
|
|
||||||
interface IStrategyChangeProps {
|
|
||||||
onDiscard: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ChangeItemWrapper = styled(Box)(({ theme }) => ({
|
export const ChangeItemWrapper = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
@ -16,19 +12,6 @@ const ChangeItemInfo: FC = styled(Box)(({ theme }) => ({
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledLink = styled(Link)(() => ({
|
|
||||||
textDecoration: 'none',
|
|
||||||
'&:hover, &:focus': {
|
|
||||||
textDecoration: 'underline',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const Discard: FC<IStrategyChangeProps> = ({ onDiscard }) => (
|
|
||||||
<Box>
|
|
||||||
<StyledLink onClick={onDiscard}>Discard</StyledLink>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const StrategyAddedChange: FC<{ discard?: ReactNode }> = ({
|
export const StrategyAddedChange: FC<{ discard?: ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
discard,
|
discard,
|
@ -3,16 +3,20 @@ import { Link } from 'react-router-dom';
|
|||||||
import { Alert, Box, Card, Typography } from '@mui/material';
|
import { Alert, Box, Card, Typography } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
interface IChangeRequestToggleChange {
|
interface IFeatureToggleChanges {
|
||||||
featureName: string;
|
featureName: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
conflict?: string;
|
conflict?: string;
|
||||||
onNavigate?: () => void;
|
onNavigate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChangeRequestFeatureToggleChange: FC<
|
export const FeatureToggleChanges: FC<IFeatureToggleChanges> = ({
|
||||||
IChangeRequestToggleChange
|
featureName,
|
||||||
> = ({ featureName, projectId, conflict, onNavigate, children }) => (
|
projectId,
|
||||||
|
conflict,
|
||||||
|
onNavigate,
|
||||||
|
children,
|
||||||
|
}) => (
|
||||||
<Card
|
<Card
|
||||||
elevation={0}
|
elevation={0}
|
||||||
sx={theme => ({
|
sx={theme => ({
|
Loading…
Reference in New Issue
Block a user