mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
Fix/strategy UI improvements (#3766)
https://linear.app/unleash/issue/1-889/ui-adjustments  --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai> Co-authored-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
parent
e075d46f79
commit
0cb6174f75
@ -24,22 +24,34 @@ export const ChangeItemWrapper = styled(Box)({
|
||||
});
|
||||
|
||||
const ChangeItemCreateEditWrapper = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'auto 40px',
|
||||
gap: theme.spacing(1),
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing(2),
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const ChangeItemInfo: FC = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '150px auto',
|
||||
gridAutoFlow: 'column',
|
||||
alignItems: 'center',
|
||||
flexGrow: 1,
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const hasNameField = (payload: unknown): payload is { name: string } =>
|
||||
typeof payload === 'object' && payload !== null && 'name' in payload;
|
||||
|
||||
const DisabledEnabledState: VFC<{ disabled: boolean }> = ({ disabled }) => {
|
||||
const DisabledEnabledState: VFC<{ show?: boolean; disabled: boolean }> = ({
|
||||
show = true,
|
||||
disabled,
|
||||
}) => {
|
||||
if (!show) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
return (
|
||||
<Tooltip
|
||||
@ -73,18 +85,16 @@ const EditHeader: VFC<{
|
||||
}> = ({ wasDisabled = false, willBeDisabled = false }) => {
|
||||
if (wasDisabled && willBeDisabled) {
|
||||
return (
|
||||
<Typography color="action.disabled">
|
||||
Editing disabled strategy
|
||||
</Typography>
|
||||
<Typography color="action.disabled">Editing strategy:</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
if (!wasDisabled && willBeDisabled) {
|
||||
return <Typography color="error.dark">Editing strategy</Typography>;
|
||||
return <Typography color="error.dark">Editing strategy:</Typography>;
|
||||
}
|
||||
|
||||
if (wasDisabled && !willBeDisabled) {
|
||||
return <Typography color="success.dark">Editing strategy</Typography>;
|
||||
return <Typography color="success.dark">Editing strategy:</Typography>;
|
||||
}
|
||||
|
||||
return <Typography>Editing strategy:</Typography>;
|
||||
@ -128,14 +138,14 @@ export const StrategyChange: VFC<{
|
||||
currentStrategy={currentStrategy}
|
||||
/>
|
||||
</StrategyTooltipLink>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(
|
||||
change.payload?.disabled === true
|
||||
)}
|
||||
show={<DisabledEnabledState disabled={true} />}
|
||||
/>
|
||||
<div>
|
||||
<DisabledEnabledState
|
||||
disabled
|
||||
show={change.payload?.disabled === true}
|
||||
/>
|
||||
</div>
|
||||
</ChangeItemInfo>
|
||||
{discard}
|
||||
<div>{discard}</div>
|
||||
</ChangeItemCreateEditWrapper>
|
||||
<StrategyExecution strategy={change.payload} />
|
||||
</>
|
||||
@ -144,9 +154,11 @@ export const StrategyChange: VFC<{
|
||||
<ChangeItemWrapper>
|
||||
<ChangeItemInfo>
|
||||
<Typography
|
||||
sx={theme => ({ color: theme.palette.error.main })}
|
||||
sx={theme => ({
|
||||
color: theme.palette.error.main,
|
||||
})}
|
||||
>
|
||||
- Deleting strategy
|
||||
- Deleting strategy:
|
||||
</Typography>
|
||||
{hasNameField(change.payload) && (
|
||||
<StrategyTooltipLink change={change}>
|
||||
@ -157,7 +169,7 @@ export const StrategyChange: VFC<{
|
||||
</StrategyTooltipLink>
|
||||
)}
|
||||
</ChangeItemInfo>
|
||||
{discard}
|
||||
<div>{discard}</div>
|
||||
</ChangeItemWrapper>
|
||||
)}
|
||||
{change.action === 'updateStrategy' && (
|
||||
@ -178,9 +190,8 @@ export const StrategyChange: VFC<{
|
||||
/>
|
||||
</StrategyTooltipLink>
|
||||
</ChangeItemInfo>
|
||||
{discard}
|
||||
<div>{discard}</div>
|
||||
</ChangeItemCreateEditWrapper>
|
||||
<StrategyExecution strategy={change.payload} />
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
change.payload?.disabled !==
|
||||
@ -190,8 +201,7 @@ export const StrategyChange: VFC<{
|
||||
<Typography
|
||||
sx={{
|
||||
marginTop: theme => theme.spacing(2),
|
||||
paddingLeft: theme => theme.spacing(3),
|
||||
paddingRight: theme => theme.spacing(3),
|
||||
marginBottom: theme => theme.spacing(2),
|
||||
...flexRow,
|
||||
gap: theme => theme.spacing(1),
|
||||
}}
|
||||
@ -203,6 +213,7 @@ export const StrategyChange: VFC<{
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
<StrategyExecution strategy={change.payload} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
@ -56,53 +56,59 @@ interface IStrategyTooltipLinkProps {
|
||||
previousTitle?: string;
|
||||
}
|
||||
|
||||
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 StrategyTooltipLink: FC<IStrategyTooltipLinkProps> = ({
|
||||
change,
|
||||
previousTitle,
|
||||
children,
|
||||
}) => (
|
||||
<>
|
||||
<StyledContainer>
|
||||
<GetFeatureStrategyIcon strategyName={change.payload.name} />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(
|
||||
previousTitle && previousTitle !== change.payload.title
|
||||
)}
|
||||
show={
|
||||
<>
|
||||
<Typography
|
||||
component="s"
|
||||
color="action.disabled"
|
||||
sx={{
|
||||
...textTruncated,
|
||||
maxWidth: '100px',
|
||||
}}
|
||||
>
|
||||
{previousTitle}
|
||||
</Typography>{' '}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<TooltipLink
|
||||
tooltip={children}
|
||||
tooltipProps={{
|
||||
maxWidth: 500,
|
||||
maxHeight: 600,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
...textTruncated,
|
||||
maxWidth:
|
||||
previousTitle === change.payload.title
|
||||
? '300px'
|
||||
: '200px',
|
||||
display: 'block',
|
||||
}}
|
||||
>
|
||||
{change.payload.title ||
|
||||
formatStrategyName(change.payload.name)}
|
||||
</Typography>
|
||||
</TooltipLink>
|
||||
</>
|
||||
<Truncated>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(
|
||||
(previousTitle && previousTitle !== change.payload.title) ||
|
||||
true
|
||||
)}
|
||||
show={
|
||||
<Truncated>
|
||||
<Typography component="s" color="text.secondary">
|
||||
{previousTitle}
|
||||
PREVIOUS consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua.
|
||||
</Typography>{' '}
|
||||
</Truncated>
|
||||
}
|
||||
/>
|
||||
<Truncated>
|
||||
<TooltipLink
|
||||
tooltip={children}
|
||||
tooltipProps={{
|
||||
maxWidth: 500,
|
||||
maxHeight: 600,
|
||||
}}
|
||||
>
|
||||
<Typography component="span">
|
||||
{change.payload.title ||
|
||||
formatStrategyName(change.payload.name)}
|
||||
lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt ut labore et dolore
|
||||
magna aliqua.
|
||||
</Typography>
|
||||
</TooltipLink>
|
||||
</Truncated>
|
||||
</Truncated>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
@ -81,7 +81,7 @@ const StyledHeader = styled('div', {
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
paddingLeft: draggable ? theme.spacing(1) : theme.spacing(2),
|
||||
color: disabled
|
||||
? theme.palette.action.disabled
|
||||
? theme.palette.text.secondary
|
||||
: theme.palette.text.primary,
|
||||
})
|
||||
);
|
||||
@ -139,7 +139,7 @@ export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||
/>
|
||||
<StyledHeaderContainer>
|
||||
<StringTruncator
|
||||
maxWidth="150"
|
||||
maxWidth="400"
|
||||
maxLength={15}
|
||||
text={formatStrategyName(
|
||||
uiConfig?.flags?.strategyImprovements
|
||||
|
@ -211,16 +211,6 @@ export const FeatureStrategyForm = ({
|
||||
/>
|
||||
</FeatureStrategyEnabled>
|
||||
<StyledHr />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(uiConfig.flags.SE)}
|
||||
show={
|
||||
<FeatureStrategySegment
|
||||
segments={segments}
|
||||
setSegments={setSegments}
|
||||
projectId={projectId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(uiConfig?.flags?.strategyImprovements)}
|
||||
show={
|
||||
@ -235,6 +225,16 @@ export const FeatureStrategyForm = ({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(uiConfig.flags.SE)}
|
||||
show={
|
||||
<FeatureStrategySegment
|
||||
segments={segments}
|
||||
setSegments={setSegments}
|
||||
projectId={projectId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<FeatureStrategyConstraints
|
||||
projectId={feature.project}
|
||||
environmentId={environmentId}
|
||||
|
@ -24,6 +24,7 @@ interface IFeatureStrategyRemoveProps {
|
||||
strategyId: string;
|
||||
disabled?: boolean;
|
||||
icon?: boolean;
|
||||
text?: boolean;
|
||||
}
|
||||
|
||||
interface IFeatureStrategyRemoveDialogueProps {
|
||||
@ -163,6 +164,7 @@ export const FeatureStrategyRemove = ({
|
||||
strategyId,
|
||||
disabled,
|
||||
icon,
|
||||
text,
|
||||
}: IFeatureStrategyRemoveProps) => {
|
||||
const [openDialogue, setOpenDialogue] = useState(false);
|
||||
|
||||
@ -197,6 +199,18 @@ export const FeatureStrategyRemove = ({
|
||||
type="button"
|
||||
>
|
||||
<Delete />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(text)}
|
||||
show={
|
||||
<Typography
|
||||
variant={'body1'}
|
||||
color={'text.secondary'}
|
||||
sx={{ ml: theme => theme.spacing(1) }}
|
||||
>
|
||||
Remove
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</PermissionIconButton>
|
||||
}
|
||||
elseShow={
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { VFC, useState } from 'react';
|
||||
import { Alert } from '@mui/material';
|
||||
import { Alert, Typography } from '@mui/material';
|
||||
import BlockIcon from '@mui/icons-material/Block';
|
||||
import TrackChangesIcon from '@mui/icons-material/TrackChanges';
|
||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||
@ -46,6 +46,18 @@ const DisableStrategy: VFC<IDisableEnableStrategyProps> = ({ ...props }) => {
|
||||
type="button"
|
||||
>
|
||||
<BlockIcon />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(props.text)}
|
||||
show={
|
||||
<Typography
|
||||
variant={'body1'}
|
||||
color={'text.secondary'}
|
||||
sx={{ ml: theme => theme.spacing(1) }}
|
||||
>
|
||||
Disable
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</PermissionIconButton>
|
||||
<Dialogue
|
||||
title={
|
||||
@ -111,6 +123,18 @@ const EnableStrategy: VFC<IDisableEnableStrategyProps> = ({ ...props }) => {
|
||||
type="button"
|
||||
>
|
||||
<TrackChangesIcon />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(props.text)}
|
||||
show={
|
||||
<Typography
|
||||
variant={'body1'}
|
||||
color={'text.secondary'}
|
||||
sx={{ ml: theme => theme.spacing(1) }}
|
||||
>
|
||||
Disable
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</PermissionIconButton>
|
||||
<Dialogue
|
||||
title={
|
||||
|
@ -5,4 +5,5 @@ export interface IDisableEnableStrategyProps {
|
||||
featureId: string;
|
||||
environmentId: string;
|
||||
strategy: IFeatureStrategy;
|
||||
text?: boolean;
|
||||
}
|
||||
|
@ -0,0 +1,134 @@
|
||||
import React, { SyntheticEvent } from 'react';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
IconButton,
|
||||
ListItem,
|
||||
Menu,
|
||||
MenuItem,
|
||||
styled,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||
import { IFeatureStrategy } from '../../../../../../../../../../interfaces/strategy';
|
||||
import { FeatureStrategyRemove } from '../../../../../../../../FeatureStrategy/FeatureStrategyRemove/FeatureStrategyRemove';
|
||||
import { DisableEnableStrategy } from '../DisableEnableStrategy/DisableEnableStrategy';
|
||||
|
||||
export interface IRemoveStrategyMenuProps {
|
||||
projectId: string;
|
||||
featureId: string;
|
||||
environmentId: string;
|
||||
strategy: IFeatureStrategy;
|
||||
}
|
||||
|
||||
const StyledContainer = styled(ListItem)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
minWidth: 'fit-content',
|
||||
padding: theme.spacing(0, 2),
|
||||
}));
|
||||
|
||||
const RemoveStrategyMenu = ({
|
||||
projectId,
|
||||
strategy,
|
||||
featureId,
|
||||
environmentId,
|
||||
}: IRemoveStrategyMenuProps) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = (event: SyntheticEvent) => {
|
||||
setAnchorEl(null);
|
||||
event.stopPropagation();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<Tooltip title="More actions">
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
size="small"
|
||||
aria-controls={open ? 'actions-menu' : undefined}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={open ? 'true' : undefined}
|
||||
>
|
||||
<MoreVertIcon sx={{ width: 32, height: 32 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
id="actions-menu"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
onClick={handleClose}
|
||||
PaperProps={{
|
||||
elevation: 0,
|
||||
sx: {
|
||||
overflow: 'visible',
|
||||
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
|
||||
mt: 1.5,
|
||||
pl: 0.5,
|
||||
minWidth: 'fit-content',
|
||||
justifyContent: 'center',
|
||||
li: {
|
||||
pl: 0,
|
||||
},
|
||||
'&:before': {
|
||||
content: '""',
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 14,
|
||||
width: 10,
|
||||
height: 10,
|
||||
bgcolor: 'background.paper',
|
||||
transform: 'translateY(-50%) rotate(45deg)',
|
||||
zIndex: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
>
|
||||
<MenuItem
|
||||
component={() => (
|
||||
<StyledContainer>
|
||||
<DisableEnableStrategy
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
environmentId={environmentId}
|
||||
strategy={strategy}
|
||||
text
|
||||
/>
|
||||
</StyledContainer>
|
||||
)}
|
||||
/>
|
||||
<MenuItem
|
||||
component={() => (
|
||||
<FeatureStrategyRemove
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
environmentId={environmentId}
|
||||
strategyId={strategy.id}
|
||||
text
|
||||
icon
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RemoveStrategyMenu;
|
@ -14,6 +14,7 @@ import { CopyStrategyIconMenu } from './CopyStrategyIconMenu/CopyStrategyIconMen
|
||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
||||
import { DisableEnableStrategy } from './DisableEnableStrategy/DisableEnableStrategy';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import RemoveStrategyMenu from './RemoveStrategyMenu/RemoveStrategyMenu';
|
||||
|
||||
interface IStrategyItemProps {
|
||||
environmentId: string;
|
||||
@ -84,20 +85,22 @@ export const StrategyItem: FC<IStrategyItemProps> = ({
|
||||
uiConfig?.flags?.strategyImprovements
|
||||
)}
|
||||
show={() => (
|
||||
<DisableEnableStrategy
|
||||
<RemoveStrategyMenu
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
environmentId={environmentId}
|
||||
strategy={strategy}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<FeatureStrategyRemove
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
environmentId={environmentId}
|
||||
strategyId={strategy.id}
|
||||
icon
|
||||
elseShow={() => (
|
||||
<FeatureStrategyRemove
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
environmentId={environmentId}
|
||||
strategyId={strategy.id}
|
||||
icon
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import useToast from 'hooks/useToast';
|
||||
import { EnvironmentVariantsCopyFrom } from './EnvironmentVariantsCopyFrom/EnvironmentVariantsCopyFrom';
|
||||
import { PushVariantsButton } from './PushVariantsButton/PushVariantsButton';
|
||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||
@ -42,7 +41,6 @@ const StyledButtonContainer = styled('div')(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const FeatureEnvironmentVariants = () => {
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
@ -3,7 +3,6 @@ import useProject from 'hooks/api/getters/useProject/useProject';
|
||||
import useLoading from 'hooks/useLoading';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import {
|
||||
StyledColumn,
|
||||
StyledDiv,
|
||||
StyledFavoriteIconButton,
|
||||
StyledHeader,
|
||||
@ -13,8 +12,6 @@ import {
|
||||
StyledSeparator,
|
||||
StyledTab,
|
||||
StyledTabContainer,
|
||||
StyledText,
|
||||
StyledTitle,
|
||||
StyledTopRow,
|
||||
} from './Project.styles';
|
||||
import { Tabs } from '@mui/material';
|
||||
|
@ -1,75 +0,0 @@
|
||||
import { Box, styled, Typography } from '@mui/material';
|
||||
import { Link } from 'react-router-dom';
|
||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
|
||||
import { StyledProjectInfoWidgetContainer } from './ProjectInfo.styles';
|
||||
|
||||
interface ILegacyHealthWidgetProps {
|
||||
projectId: string;
|
||||
health: number;
|
||||
total?: number;
|
||||
stale?: number;
|
||||
}
|
||||
|
||||
const StyledParagraphEmphasizedText = styled('p')(({ theme }) => ({
|
||||
fontSize: '1.5rem',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
fontSize: theme.fontSizes.bodySize,
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledDivPercentageContainer = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}));
|
||||
|
||||
const StyledLink = styled(Link)(({ theme }) => ({
|
||||
textDecoration: 'none',
|
||||
...flexRow,
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.primary.main,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
position: 'absolute',
|
||||
bottom: theme.spacing(1.5),
|
||||
right: theme.spacing(1.5),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledSpanLinkText = styled('p')(({ theme }) => ({
|
||||
[theme.breakpoints.down('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledArrowIcon = styled(ArrowForwardIcon)(({ theme }) => ({
|
||||
color: theme.palette.primary.main,
|
||||
marginLeft: theme.spacing(1),
|
||||
}));
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const LegacyHealthWidget = ({
|
||||
projectId,
|
||||
health,
|
||||
}: ILegacyHealthWidgetProps) => (
|
||||
<StyledProjectInfoWidgetContainer>
|
||||
<StyledDivPercentageContainer>
|
||||
<PercentageCircle percentage={health} />
|
||||
</StyledDivPercentageContainer>
|
||||
<Typography data-loading sx={{ marginTop: theme => theme.spacing(2) }}>
|
||||
Overall health rating
|
||||
</Typography>
|
||||
<Box sx={{ marginBottom: theme => theme.spacing(2.5) }}>
|
||||
<StyledParagraphEmphasizedText data-loading>
|
||||
{health}%
|
||||
</StyledParagraphEmphasizedText>
|
||||
</Box>
|
||||
<StyledLink data-loading to={`/projects/${projectId}/health`}>
|
||||
<StyledSpanLinkText data-loading>view more </StyledSpanLinkText>
|
||||
<StyledArrowIcon data-loading />
|
||||
</StyledLink>
|
||||
</StyledProjectInfoWidgetContainer>
|
||||
);
|
@ -1,93 +0,0 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
import { styled } from '@mui/material';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
const StyledDivInfoContainer = styled('div')(({ theme }) => ({
|
||||
textAlign: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
width: '100%',
|
||||
padding: theme.spacing(3, 2, 3, 2),
|
||||
[theme.breakpoints.down('md')]: {
|
||||
...flexRow,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
position: 'relative',
|
||||
padding: theme.spacing(1.5),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledParagraphSubtitle = styled('p')(({ theme }) => ({
|
||||
marginBottom: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const StyledParagraphEmphasizedText = styled('p')(({ theme }) => ({
|
||||
fontSize: '1.5rem',
|
||||
marginBottom: theme.spacing(2),
|
||||
[theme.breakpoints.down('md')]: {
|
||||
fontSize: theme.fontSizes.bodySize,
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledSpanLinkText = styled('p')(({ theme }) => ({
|
||||
[theme.breakpoints.down('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledLink = styled(Link)(({ theme }) => ({
|
||||
textDecoration: 'none',
|
||||
...flexRow,
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.primary.main,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
position: 'absolute',
|
||||
right: theme.spacing(1.5),
|
||||
bottom: theme.spacing(1.5),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledArrowIcon = styled(ArrowForwardIcon)(({ theme }) => ({
|
||||
color: theme.palette.primary.main,
|
||||
marginLeft: theme.spacing(1),
|
||||
}));
|
||||
|
||||
interface ILegacyProjectMembersWidgetProps {
|
||||
projectId: string;
|
||||
memberCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const LegacyProjectMembersWidget = ({
|
||||
projectId,
|
||||
memberCount,
|
||||
}: ILegacyProjectMembersWidgetProps) => {
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
let link = `/admin/users`;
|
||||
|
||||
if (uiConfig?.versionInfo?.current?.enterprise) {
|
||||
link = `/projects/${projectId}/settings/access`;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledDivInfoContainer>
|
||||
<StyledParagraphSubtitle data-loading>
|
||||
Project members
|
||||
</StyledParagraphSubtitle>
|
||||
<StyledParagraphEmphasizedText data-loading>
|
||||
{memberCount}
|
||||
</StyledParagraphEmphasizedText>
|
||||
<StyledLink data-loading to={link}>
|
||||
<StyledSpanLinkText data-loading>view more </StyledSpanLinkText>
|
||||
<StyledArrowIcon data-loading />
|
||||
</StyledLink>
|
||||
</StyledDivInfoContainer>
|
||||
);
|
||||
};
|
@ -10,8 +10,6 @@ import { ProjectMembersWidget } from './ProjectMembersWidget';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { ChangeRequestsWidget } from './ChangeRequestsWidget';
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
import { LegacyHealthWidget } from './LegacyHealthWidget';
|
||||
import { LegacyProjectMembersWidget } from './LegacyProjectMembersWidget';
|
||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
|
||||
interface IProjectInfoProps {
|
||||
@ -48,7 +46,7 @@ const ProjectInfo = ({
|
||||
features,
|
||||
stats,
|
||||
}: IProjectInfoProps) => {
|
||||
const { uiConfig, isEnterprise } = useUiConfig();
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const { isChangeRequestConfiguredInAnyEnv } = useChangeRequestsEnabled(id);
|
||||
|
@ -42,7 +42,6 @@ const ProjectOverview = () => {
|
||||
project;
|
||||
usePageTitle(`Project overview – ${projectName}`);
|
||||
const { setLastViewed } = useLastViewedProject();
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
useEffect(() => {
|
||||
setLastViewed(projectId);
|
||||
|
@ -3,11 +3,11 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { useStrategy } from 'hooks/api/getters/useStrategy/useStrategy';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
|
||||
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
||||
import { IFeatureStrategy, IStrategy } from 'interfaces/strategy';
|
||||
import { IStrategy } from 'interfaces/strategy';
|
||||
import { useRequiredQueryParam } from 'hooks/useRequiredQueryParam';
|
||||
import { ISegment } from 'interfaces/segment';
|
||||
import { useFormErrors } from 'hooks/useFormErrors';
|
||||
@ -42,7 +42,7 @@ const EditDefaultStrategy = ({ strategy }: EditDefaultStrategyProps) => {
|
||||
const { unleashUrl } = uiConfig;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [previousTitle, setPreviousTitle] = useState<string>('');
|
||||
const [previousTitle] = useState<string>('');
|
||||
const { trackEvent } = usePlausibleTracker();
|
||||
|
||||
const trackTitle = (title: string = '') => {
|
||||
|
@ -27,13 +27,11 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
||||
import { Search } from 'component/common/Search/Search';
|
||||
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
|
||||
|
||||
export const SegmentTable = () => {
|
||||
const projectId = useOptionalPathParam('projectId');
|
||||
const { segments, loading } = useSegments();
|
||||
const { uiConfig } = useUiConfig();
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const [initialState] = useState({
|
||||
sortBy: [{ id: 'createdAt' }],
|
||||
|
Loading…
Reference in New Issue
Block a user