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