mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-26 01:17:00 +02:00
Refactor/make styles batch 6 part 2 (#2811)
Adds another batch of refactored components
This commit is contained in:
parent
b631618532
commit
093156f5f5
@ -33,7 +33,7 @@ export const FeatureStrategyItem = ({
|
||||
style={{
|
||||
borderColor: result.enabled
|
||||
? theme.palette.success.main
|
||||
: 'inherit',
|
||||
: 'none',
|
||||
}}
|
||||
strategy={{ ...strategy, id: `${objectId(strategy)}` }}
|
||||
orderNumber={index + 1}
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Chip, Typography, useTheme } from '@mui/material';
|
||||
import { Chip, Typography, useTheme, styled } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './PlaygroundParametertem.styles';
|
||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||
import { CancelOutlined } from '@mui/icons-material';
|
||||
import classnames from 'classnames';
|
||||
|
||||
interface IConstraintItemProps {
|
||||
value: Array<string | number>;
|
||||
@ -12,29 +10,55 @@ interface IConstraintItemProps {
|
||||
showReason?: boolean;
|
||||
}
|
||||
|
||||
const StyledDivContainer = styled('div', {
|
||||
shouldForwardProp: prop => prop !== 'showReason',
|
||||
})<{ showReason?: boolean }>(({ theme, showReason }) => ({
|
||||
width: '100%',
|
||||
padding: theme.spacing(2, 3),
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: theme.spacing(2),
|
||||
opacity: showReason ? 0.9 : 1,
|
||||
backgroundColor: showReason ? theme.palette.background.paper : 'inherit',
|
||||
}));
|
||||
|
||||
const StyledDivColumn = styled('div')(({ theme }) => ({
|
||||
flexDirection: 'column',
|
||||
}));
|
||||
|
||||
const StyledChip = styled(Chip)(({ theme }) => ({
|
||||
margin: theme.spacing(0.5),
|
||||
}));
|
||||
|
||||
const StyledParagraph = styled('p')(({ theme }) => ({
|
||||
display: 'inline',
|
||||
margin: theme.spacing(0.5, 0),
|
||||
maxWidth: '95%',
|
||||
textAlign: 'center',
|
||||
wordBreak: 'break-word',
|
||||
}));
|
||||
|
||||
export const PlaygroundParameterItem = ({
|
||||
value,
|
||||
text,
|
||||
input,
|
||||
showReason = false,
|
||||
}: IConstraintItemProps) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const theme = useTheme();
|
||||
|
||||
const color = input === 'no value' ? 'error' : 'neutral';
|
||||
const reason = `value does not match any ${text}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
styles.container,
|
||||
showReason ? styles.disabled : ''
|
||||
)}
|
||||
>
|
||||
<StyledDivContainer showReason={showReason}>
|
||||
<Typography variant="subtitle1" color={theme.palette[color].main}>
|
||||
{`${input}`}
|
||||
</Typography>
|
||||
<div className={styles.column}>
|
||||
<StyledDivColumn>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(showReason)}
|
||||
show={
|
||||
@ -51,13 +75,13 @@ export const PlaygroundParameterItem = ({
|
||||
show={<p>No {text}s added yet.</p>}
|
||||
elseShow={
|
||||
<div>
|
||||
<p className={styles.paragraph}>
|
||||
<StyledParagraph>
|
||||
{value.length}{' '}
|
||||
{value.length > 1 ? `${text}s` : text} will get
|
||||
access.
|
||||
</p>
|
||||
</StyledParagraph>
|
||||
{value.map((v: string | number) => (
|
||||
<Chip
|
||||
<StyledChip
|
||||
key={v}
|
||||
label={
|
||||
<StringTruncator
|
||||
@ -66,18 +90,17 @@ export const PlaygroundParameterItem = ({
|
||||
maxLength={50}
|
||||
/>
|
||||
}
|
||||
className={styles.chip}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</StyledDivColumn>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(showReason)}
|
||||
show={<CancelOutlined color={'error'} />}
|
||||
elseShow={<div />}
|
||||
/>
|
||||
</div>
|
||||
</StyledDivContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
width: '100%',
|
||||
padding: theme.spacing(2, 3),
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: theme.spacing(2),
|
||||
},
|
||||
disabled: {
|
||||
backgroundColor: theme.palette.neutral.light,
|
||||
opacity: '90%',
|
||||
},
|
||||
chip: {
|
||||
margin: '0.25rem',
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
paragraph: {
|
||||
display: 'inline',
|
||||
margin: '0.25rem 0',
|
||||
maxWidth: '95%',
|
||||
textAlign: 'center',
|
||||
wordBreak: 'break-word',
|
||||
},
|
||||
}));
|
@ -1,61 +1,87 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import { styled, Tab } from '@mui/material';
|
||||
import { FavoriteIconButton } from 'component/common/FavoriteIconButton/FavoriteIconButton';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
containerStyles: {
|
||||
display: 'flex',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
export const StyledDiv = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
}));
|
||||
|
||||
export const StyledTopRow = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
export const StyledColumn = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}));
|
||||
|
||||
export const StyledName = styled('div')(() => ({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}));
|
||||
|
||||
export const StyledTitle = styled('span')(({ theme }) => ({
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
fontWeight: 'normal',
|
||||
}));
|
||||
|
||||
export const StyledText = styled(StyledTitle)(({ theme }) => ({
|
||||
color: theme.palette.neutral.dark,
|
||||
}));
|
||||
|
||||
export const StyledFavoriteIconButton = styled(FavoriteIconButton)(
|
||||
({ theme }) => ({
|
||||
marginLeft: theme.spacing(-1.5),
|
||||
})
|
||||
);
|
||||
|
||||
export const StyledHeader = styled('div')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
marginBottom: theme.spacing(2),
|
||||
}));
|
||||
|
||||
export const StyledInnerContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(2.5, 5),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'start',
|
||||
}));
|
||||
|
||||
export const StyledProjectTitle = styled('h2')(({ theme }) => ({
|
||||
margin: 0,
|
||||
width: '100%',
|
||||
fontSize: theme.fontSizes.mainHeader,
|
||||
fontWeight: 'bold',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(2),
|
||||
}));
|
||||
|
||||
export const StyledSeparator = styled('div')(({ theme }) => ({
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.tertiary.light,
|
||||
height: '1px',
|
||||
}));
|
||||
|
||||
export const StyledTabContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(0, 4),
|
||||
}));
|
||||
|
||||
export const StyledTab = styled(Tab)(({ theme }) => ({
|
||||
textTransform: 'none',
|
||||
fontSize: theme.fontSizes.bodySize,
|
||||
flexGrow: 1,
|
||||
flexBasis: 0,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
paddingLeft: theme.spacing(1),
|
||||
paddingRight: theme.spacing(1),
|
||||
},
|
||||
projectToggles: {
|
||||
width: '100%',
|
||||
minWidth: 0,
|
||||
},
|
||||
header: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
marginBottom: '1rem',
|
||||
},
|
||||
innerContainer: {
|
||||
padding: '1.25rem 2rem',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'start',
|
||||
},
|
||||
separator: {
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.grey[200],
|
||||
height: '1px',
|
||||
},
|
||||
tabContainer: {
|
||||
padding: '0 2rem',
|
||||
},
|
||||
tabButton: {
|
||||
textTransform: 'none',
|
||||
fontSize: '1rem',
|
||||
flexGrow: 1,
|
||||
flexBasis: 0,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
paddingLeft: theme.spacing(1),
|
||||
paddingRight: theme.spacing(1),
|
||||
},
|
||||
[theme.breakpoints.up('md')]: {
|
||||
minWidth: 160,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
margin: 0,
|
||||
width: '100%',
|
||||
fontSize: theme.fontSizes.mainHeader,
|
||||
fontWeight: 'bold',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
gap: '1rem',
|
||||
},
|
||||
titleText: {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
minWidth: 160,
|
||||
},
|
||||
}));
|
||||
|
@ -2,8 +2,22 @@ import { useNavigate } from 'react-router';
|
||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
||||
import useLoading from 'hooks/useLoading';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './Project.styles';
|
||||
import { styled, Tab, Tabs } from '@mui/material';
|
||||
import {
|
||||
StyledColumn,
|
||||
StyledDiv,
|
||||
StyledFavoriteIconButton,
|
||||
StyledHeader,
|
||||
StyledInnerContainer,
|
||||
StyledName,
|
||||
StyledProjectTitle,
|
||||
StyledSeparator,
|
||||
StyledTab,
|
||||
StyledTabContainer,
|
||||
StyledText,
|
||||
StyledTitle,
|
||||
StyledTopRow,
|
||||
} from './Project.styles';
|
||||
import { Tabs } from '@mui/material';
|
||||
import { Delete, Edit } from '@mui/icons-material';
|
||||
import useToast from 'hooks/useToast';
|
||||
import useQueryParams from 'hooks/useQueryParams';
|
||||
@ -28,53 +42,17 @@ import { MainLayout } from 'component/layout/MainLayout/MainLayout';
|
||||
import { ProjectChangeRequests } from '../../changeRequest/ProjectChangeRequests/ProjectChangeRequests';
|
||||
import { ProjectSettings } from './ProjectSettings/ProjectSettings';
|
||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
import { FavoriteIconButton } from 'component/common/FavoriteIconButton/FavoriteIconButton';
|
||||
import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
|
||||
|
||||
const StyledDiv = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
}));
|
||||
|
||||
const StyledTopRow = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const Column = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}));
|
||||
|
||||
const StyledName = styled('div')(() => ({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}));
|
||||
|
||||
const StyledTitle = styled('span')(({ theme }) => ({
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
fontWeight: 'normal',
|
||||
}));
|
||||
const StyledText = styled(StyledTitle)(({ theme }) => ({
|
||||
color: theme.palette.grey[800],
|
||||
}));
|
||||
|
||||
const StyledFavoriteIconButton = styled(FavoriteIconButton)(({ theme }) => ({
|
||||
marginLeft: theme.spacing(-1.5),
|
||||
}));
|
||||
|
||||
const Project = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const params = useQueryParams();
|
||||
const { project, loading, refetch } = useProject(projectId);
|
||||
const ref = useLoading(loading);
|
||||
const { setToastData } = useToast();
|
||||
const { classes: styles } = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
const { isOss, uiConfig } = useUiConfig();
|
||||
const { isOss } = useUiConfig();
|
||||
const basePath = `/projects/${projectId}`;
|
||||
const projectName = project?.name || projectId;
|
||||
const { isChangeRequestConfiguredInAnyEnv } =
|
||||
@ -152,19 +130,19 @@ const Project = () => {
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.innerContainer}>
|
||||
<StyledHeader>
|
||||
<StyledInnerContainer>
|
||||
<StyledTopRow>
|
||||
<StyledDiv>
|
||||
<StyledFavoriteIconButton
|
||||
onClick={onFavorite}
|
||||
isFavorite={project?.favorite}
|
||||
/>
|
||||
<h2 className={styles.title}>
|
||||
<StyledProjectTitle>
|
||||
<StyledName data-loading>
|
||||
{projectName}
|
||||
</StyledName>
|
||||
</h2>
|
||||
</StyledProjectTitle>
|
||||
</StyledDiv>
|
||||
<StyledDiv>
|
||||
<PermissionIconButton
|
||||
@ -197,8 +175,8 @@ const Project = () => {
|
||||
</PermissionIconButton>
|
||||
</StyledDiv>
|
||||
</StyledTopRow>
|
||||
<Column>
|
||||
<h2 className={styles.title}>
|
||||
<StyledColumn>
|
||||
<StyledProjectTitle>
|
||||
<div>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(project.description)}
|
||||
@ -222,12 +200,12 @@ const Project = () => {
|
||||
</StyledText>
|
||||
</StyledDiv>
|
||||
</div>
|
||||
</h2>
|
||||
</Column>
|
||||
</div>
|
||||
</StyledProjectTitle>
|
||||
</StyledColumn>
|
||||
</StyledInnerContainer>
|
||||
|
||||
<div className={styles.separator} />
|
||||
<div className={styles.tabContainer}>
|
||||
<StyledSeparator />
|
||||
<StyledTabContainer>
|
||||
<Tabs
|
||||
value={activeTab?.path}
|
||||
indicatorColor="primary"
|
||||
@ -236,17 +214,16 @@ const Project = () => {
|
||||
allowScrollButtonsMobile
|
||||
>
|
||||
{tabs.map(tab => (
|
||||
<Tab
|
||||
<StyledTab
|
||||
key={tab.title}
|
||||
label={tab.title}
|
||||
value={tab.path}
|
||||
onClick={() => navigate(tab.path)}
|
||||
className={styles.tabButton}
|
||||
/>
|
||||
))}
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</StyledTabContainer>
|
||||
</StyledHeader>
|
||||
<DeleteProjectDialogue
|
||||
project={projectId}
|
||||
open={showDelDialog}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
cell: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
menuContainer: {
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
padding: theme.spacing(1, 1.5),
|
||||
},
|
||||
item: {
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
},
|
||||
text: {
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
},
|
||||
}));
|
@ -9,19 +9,26 @@ import {
|
||||
Popover,
|
||||
Tooltip,
|
||||
Typography,
|
||||
styled,
|
||||
} from '@mui/material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||
import FileCopyIcon from '@mui/icons-material/FileCopy';
|
||||
import ArchiveIcon from '@mui/icons-material/Archive';
|
||||
import WatchLaterIcon from '@mui/icons-material/WatchLater';
|
||||
import { useStyles } from './ActionsCell.styles';
|
||||
import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC';
|
||||
import {
|
||||
CREATE_FEATURE,
|
||||
DELETE_FEATURE,
|
||||
UPDATE_FEATURE,
|
||||
} from 'component/providers/AccessProvider/permissions';
|
||||
import { defaultBorderRadius } from 'themes/themeStyles';
|
||||
|
||||
const StyledBoxCell = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
paddingRight: theme.spacing(2),
|
||||
}));
|
||||
|
||||
interface IActionsCellProps {
|
||||
projectId: string;
|
||||
@ -42,7 +49,6 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
onOpenStaleDialog,
|
||||
}) => {
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const { classes } = useStyles();
|
||||
const {
|
||||
original: { name: featureId, stale },
|
||||
} = row;
|
||||
@ -58,7 +64,7 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
const menuId = `${id}-menu`;
|
||||
|
||||
return (
|
||||
<Box className={classes.cell}>
|
||||
<StyledBoxCell>
|
||||
<Tooltip title="Feature toggle actions" arrow describeChild>
|
||||
<IconButton
|
||||
id={id}
|
||||
@ -80,7 +86,10 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
disableScrollLock={true}
|
||||
PaperProps={{
|
||||
className: classes.menuContainer,
|
||||
sx: theme => ({
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
padding: theme.spacing(1, 1.5),
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<MenuList aria-labelledby={id}>
|
||||
@ -90,7 +99,7 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
>
|
||||
{({ hasAccess }) => (
|
||||
<MenuItem
|
||||
className={classes.item}
|
||||
sx={defaultBorderRadius}
|
||||
onClick={handleClose}
|
||||
disabled={!hasAccess}
|
||||
component={RouterLink}
|
||||
@ -113,7 +122,7 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
>
|
||||
{({ hasAccess }) => (
|
||||
<MenuItem
|
||||
className={classes.item}
|
||||
sx={defaultBorderRadius}
|
||||
onClick={() => {
|
||||
onOpenArchiveDialog(featureId);
|
||||
handleClose();
|
||||
@ -137,7 +146,7 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
>
|
||||
{({ hasAccess }) => (
|
||||
<MenuItem
|
||||
className={classes.item}
|
||||
sx={defaultBorderRadius}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
onOpenStaleDialog({
|
||||
@ -160,6 +169,6 @@ export const ActionsCell: VFC<IActionsCellProps> = ({
|
||||
</PermissionHOC>
|
||||
</MenuList>
|
||||
</Popover>
|
||||
</Box>
|
||||
</StyledBoxCell>
|
||||
);
|
||||
};
|
||||
|
@ -1,35 +1,41 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
Divider,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
styled,
|
||||
} from '@mui/material';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing(-1, 0),
|
||||
},
|
||||
menuContainer: {
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
paddingBottom: theme.spacing(2),
|
||||
},
|
||||
menuHeader: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: theme.spacing(1, 1, 0, 4),
|
||||
},
|
||||
menuItem: {
|
||||
padding: theme.spacing(0, 2),
|
||||
margin: theme.spacing(0, 2),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
},
|
||||
checkbox: {
|
||||
padding: theme.spacing(0.75, 1),
|
||||
},
|
||||
divider: {
|
||||
'&.MuiDivider-root.MuiDivider-fullWidth': {
|
||||
margin: theme.spacing(0.75, 0),
|
||||
},
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
|
||||
export const StyledBoxContainer = styled(Box)(() => ({
|
||||
...flexRow,
|
||||
justifyContent: 'center',
|
||||
}));
|
||||
|
||||
export const StyledIconButton = styled(IconButton)(({ theme }) => ({
|
||||
margin: theme.spacing(-1, 0),
|
||||
}));
|
||||
|
||||
export const StyledBoxMenuHeader = styled(Box)(({ theme }) => ({
|
||||
...flexRow,
|
||||
justifyContent: 'space-between',
|
||||
padding: theme.spacing(1, 1, 0, 4),
|
||||
}));
|
||||
|
||||
export const StyledMenuItem = styled(MenuItem)(({ theme }) => ({
|
||||
padding: theme.spacing(0, 2),
|
||||
margin: theme.spacing(0, 2),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
}));
|
||||
|
||||
export const StyledDivider = styled(Divider)(({ theme }) => ({
|
||||
'&.MuiDivider-root.MuiDivider-fullWidth': {
|
||||
margin: theme.spacing(0.75, 0),
|
||||
},
|
||||
}));
|
||||
|
||||
export const StyledCheckbox = styled(Checkbox)(({ theme }) => ({
|
||||
padding: theme.spacing(0.75, 1),
|
||||
}));
|
||||
|
@ -1,12 +1,8 @@
|
||||
import { useEffect, useState, VFC } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
Divider,
|
||||
IconButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Popover,
|
||||
Tooltip,
|
||||
@ -17,7 +13,14 @@ import {
|
||||
import ColumnIcon from '@mui/icons-material/ViewWeek';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './ColumnsMenu.styles';
|
||||
import {
|
||||
StyledBoxContainer,
|
||||
StyledBoxMenuHeader,
|
||||
StyledCheckbox,
|
||||
StyledDivider,
|
||||
StyledIconButton,
|
||||
StyledMenuItem,
|
||||
} from './ColumnsMenu.styles';
|
||||
|
||||
interface IColumnsMenuProps {
|
||||
allColumns: {
|
||||
@ -51,7 +54,6 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
setHiddenColumns,
|
||||
}) => {
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const { classes } = useStyles();
|
||||
const theme = useTheme();
|
||||
const isTinyScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
@ -104,9 +106,9 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
const menuId = `columns-menu-list-${id}`;
|
||||
|
||||
return (
|
||||
<Box className={classes.container}>
|
||||
<StyledBoxContainer>
|
||||
<Tooltip title="Select columns" arrow describeChild>
|
||||
<IconButton
|
||||
<StyledIconButton
|
||||
id={id}
|
||||
aria-controls={isOpen ? menuId : undefined}
|
||||
aria-haspopup="true"
|
||||
@ -114,11 +116,10 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
onClick={handleClick}
|
||||
type="button"
|
||||
size="large"
|
||||
className={classes.button}
|
||||
data-loading
|
||||
>
|
||||
<ColumnIcon />
|
||||
</IconButton>
|
||||
</StyledIconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Popover
|
||||
@ -136,34 +137,36 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
}}
|
||||
disableScrollLock={true}
|
||||
PaperProps={{
|
||||
className: classes.menuContainer,
|
||||
sx: theme => ({
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
paddingBottom: theme.spacing(2),
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box className={classes.menuHeader}>
|
||||
<StyledBoxMenuHeader>
|
||||
<Typography variant="body2">
|
||||
<strong>Columns</strong>
|
||||
</Typography>
|
||||
<IconButton onClick={handleClose}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</StyledBoxMenuHeader>
|
||||
<MenuList>
|
||||
{allColumns
|
||||
.filter(({ hideInMenu }) => !hideInMenu)
|
||||
.map(column => [
|
||||
<ConditionallyRender
|
||||
condition={dividerBefore.includes(column.id)}
|
||||
show={<Divider className={classes.divider} />}
|
||||
show={<StyledDivider />}
|
||||
/>,
|
||||
<MenuItem
|
||||
<StyledMenuItem
|
||||
onClick={() =>
|
||||
column.toggleHidden(column.isVisible)
|
||||
}
|
||||
disabled={staticColumns.includes(column.id)}
|
||||
className={classes.menuItem}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Checkbox
|
||||
<StyledCheckbox
|
||||
edge="start"
|
||||
checked={column.isVisible}
|
||||
disableRipple
|
||||
@ -171,7 +174,6 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
'aria-labelledby': column.id,
|
||||
}}
|
||||
size="medium"
|
||||
className={classes.checkbox}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
@ -195,14 +197,14 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</MenuItem>,
|
||||
</StyledMenuItem>,
|
||||
<ConditionallyRender
|
||||
condition={dividerAfter.includes(column.id)}
|
||||
show={<Divider className={classes.divider} />}
|
||||
show={<StyledDivider />}
|
||||
/>,
|
||||
])}
|
||||
</MenuList>
|
||||
</Popover>
|
||||
</Box>
|
||||
</StyledBoxContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
mx: 'auto',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
}));
|
@ -1,9 +1,14 @@
|
||||
import { VFC } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { Box, styled } from '@mui/material';
|
||||
import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch';
|
||||
import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions';
|
||||
import { useOptimisticUpdate } from './hooks/useOptimisticUpdate';
|
||||
import { useStyles } from './FeatureToggleSwitch.styles';
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
|
||||
const StyledBoxContainer = styled(Box)(() => ({
|
||||
mx: 'auto',
|
||||
...flexRow,
|
||||
}));
|
||||
|
||||
interface IFeatureToggleSwitchProps {
|
||||
featureName: string;
|
||||
@ -25,7 +30,6 @@ export const FeatureToggleSwitch: VFC<IFeatureToggleSwitchProps> = ({
|
||||
value,
|
||||
onToggle,
|
||||
}) => {
|
||||
const { classes } = useStyles();
|
||||
const [isChecked, setIsChecked, rollbackIsChecked] =
|
||||
useOptimisticUpdate<boolean>(value);
|
||||
|
||||
@ -37,8 +41,7 @@ export const FeatureToggleSwitch: VFC<IFeatureToggleSwitchProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={classes.container}
|
||||
<StyledBoxContainer
|
||||
key={`${featureName}-${environmentName}`} // Prevent animation when archiving rows
|
||||
>
|
||||
<PermissionSwitch
|
||||
@ -50,6 +53,6 @@ export const FeatureToggleSwitch: VFC<IFeatureToggleSwitchProps> = ({
|
||||
onClick={onClick}
|
||||
disabled={isChecked !== value}
|
||||
/>
|
||||
</Box>
|
||||
</StyledBoxContainer>
|
||||
);
|
||||
};
|
||||
|
@ -13,60 +13,4 @@ export const useStyles = makeStyles()(theme => ({
|
||||
width: 'inherit',
|
||||
},
|
||||
},
|
||||
headerClass: {
|
||||
'& th': {
|
||||
fontSize: theme.fontSizes.smallerBody,
|
||||
lineHeight: '1rem',
|
||||
},
|
||||
},
|
||||
bodyClass: {
|
||||
overflowX: 'auto',
|
||||
padding: theme.spacing(4),
|
||||
},
|
||||
header: {
|
||||
padding: '1rem',
|
||||
},
|
||||
title: {
|
||||
display: 'unset',
|
||||
},
|
||||
iconButton: {
|
||||
marginRight: '1rem',
|
||||
},
|
||||
icon: {
|
||||
color: '#000',
|
||||
height: '30px',
|
||||
width: '30px',
|
||||
},
|
||||
noTogglesFound: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
link: {
|
||||
textDecoration: 'none',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
actionsContainer: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
search: {
|
||||
border: `1px solid ${theme.palette.grey[300]}`,
|
||||
height: 35,
|
||||
marginRight: '2rem',
|
||||
},
|
||||
button: {
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
row: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
},
|
||||
cell: {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
'& > *': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useMediaQuery, useTheme } from '@mui/material';
|
||||
import { styled, useMediaQuery, useTheme } from '@mui/material';
|
||||
import { Add } from '@mui/icons-material';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||
@ -9,7 +9,6 @@ import { PageContent } from 'component/common/PageContent/PageContent';
|
||||
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
||||
import { getCreateTogglePath } from 'utils/routePathHelpers';
|
||||
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { DateCell } from 'component/common/Table/cells/DateCell/DateCell';
|
||||
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
||||
@ -47,6 +46,10 @@ import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/Feat
|
||||
import { useGlobalLocalStorage } from 'hooks/useGlobalLocalStorage';
|
||||
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
||||
|
||||
const StyledResponsiveButton = styled(ResponsiveButton)(() => ({
|
||||
whiteSpace: 'nowrap',
|
||||
}));
|
||||
|
||||
interface IProjectFeatureTogglesProps {
|
||||
features: IProject['features'];
|
||||
environments: IProject['environments'];
|
||||
@ -102,7 +105,6 @@ export const ProjectFeatureToggles = ({
|
||||
useGlobalLocalStorage();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
||||
const environments = useEnvironmentsRef(
|
||||
loading ? ['a', 'b', 'c'] : newEnvironments
|
||||
@ -488,10 +490,8 @@ export const ProjectFeatureToggles = ({
|
||||
<PageContent
|
||||
isLoading={loading}
|
||||
className={styles.container}
|
||||
bodyClass={styles.bodyClass}
|
||||
header={
|
||||
<PageHeader
|
||||
className={styles.title}
|
||||
titleElement={`Feature toggles (${rows.length})`}
|
||||
actions={
|
||||
<>
|
||||
@ -515,7 +515,7 @@ export const ProjectFeatureToggles = ({
|
||||
setHiddenColumns={setHiddenColumns}
|
||||
/>
|
||||
<PageHeader.Divider sx={{ marginLeft: 0 }} />
|
||||
<ResponsiveButton
|
||||
<StyledResponsiveButton
|
||||
onClick={() =>
|
||||
navigate(getCreateTogglePath(projectId))
|
||||
}
|
||||
@ -523,10 +523,9 @@ export const ProjectFeatureToggles = ({
|
||||
Icon={Add}
|
||||
projectId={projectId}
|
||||
permission={CREATE_FEATURE}
|
||||
className={styles.button}
|
||||
>
|
||||
New feature toggle
|
||||
</ResponsiveButton>
|
||||
</StyledResponsiveButton>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import useProject, {
|
||||
useProjectNameOrId,
|
||||
} from 'hooks/api/getters/useProject/useProject';
|
||||
import { styled } from '@mui/material';
|
||||
import { ProjectFeatureToggles } from './ProjectFeatureToggles/ProjectFeatureToggles';
|
||||
import ProjectInfo from './ProjectInfo/ProjectInfo';
|
||||
import { useStyles } from './Project.styles';
|
||||
import { usePageTitle } from 'hooks/usePageTitle';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { useLastViewedProject } from '../../../hooks/useLastViewedProject';
|
||||
@ -11,12 +11,23 @@ import { useEffect } from 'react';
|
||||
|
||||
const refreshInterval = 15 * 1000;
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledProjectToggles = styled('div')(() => ({
|
||||
width: '100%',
|
||||
minWidth: 0,
|
||||
}));
|
||||
|
||||
const ProjectOverview = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const projectName = useProjectNameOrId(projectId);
|
||||
const { project, loading } = useProject(projectId, { refreshInterval });
|
||||
const { members, features, health, description, environments } = project;
|
||||
const { classes: styles } = useStyles();
|
||||
usePageTitle(`Project overview – ${projectName}`);
|
||||
const { setLastViewed } = useLastViewedProject();
|
||||
|
||||
@ -25,7 +36,7 @@ const ProjectOverview = () => {
|
||||
}, [projectId, setLastViewed]);
|
||||
|
||||
return (
|
||||
<div className={styles.containerStyles}>
|
||||
<StyledContainer>
|
||||
<ProjectInfo
|
||||
id={projectId}
|
||||
description={description}
|
||||
@ -33,14 +44,14 @@ const ProjectOverview = () => {
|
||||
health={health}
|
||||
featureCount={features?.length}
|
||||
/>
|
||||
<div className={styles.projectToggles}>
|
||||
<StyledProjectToggles>
|
||||
<ProjectFeatureToggles
|
||||
features={features}
|
||||
environments={environments}
|
||||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</StyledProjectToggles>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,11 @@ export const focusable = (theme: Theme) => ({
|
||||
export const flexRow = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
};
|
||||
} as const;
|
||||
|
||||
export const defaultBorderRadius = (theme: Theme) => ({
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
});
|
||||
|
||||
/**
|
||||
* Please extract styles below into MUI fragments as shown above
|
||||
|
Loading…
Reference in New Issue
Block a user