1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-01 01:18:10 +02:00

Refactor/make styles batch 6 part 3 (#2823)

Last set of components refactoring for batch 6
This commit is contained in:
Fredrik Strand Oseberg 2023-01-05 09:45:17 +01:00 committed by GitHub
parent 005e4b6858
commit 94c90b7731
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 351 additions and 386 deletions

View File

@ -29,6 +29,7 @@ interface IPermissionIconButtonProps {
interface IButtonProps extends IPermissionIconButtonProps {
onClick: (event: React.SyntheticEvent) => void;
style?: React.CSSProperties;
}
interface ILinkProps extends IPermissionIconButtonProps {
@ -107,6 +108,7 @@ const PermissionIconButton = (props: IButtonProps | ILinkProps) => {
/>
);
}
return <RootPermissionIconButton {...props} />;
};

View File

@ -1,39 +1,36 @@
import { makeStyles } from 'tss-react/mui';
import Input from 'component/common/Input/Input';
import { TextField, Button, styled } from '@mui/material';
export const useStyles = makeStyles()(theme => ({
form: {
display: 'flex',
flexDirection: 'column',
height: '100%',
},
container: {
maxWidth: '400px',
},
input: { width: '100%', marginBottom: '1rem' },
label: {
minWidth: '300px',
[theme.breakpoints.down(600)]: {
minWidth: 'auto',
},
},
buttonContainer: {
marginTop: 'auto',
display: 'flex',
justifyContent: 'flex-end',
},
cancelButton: {
marginLeft: '1.5rem',
},
inputDescription: {
marginBottom: '0.5rem',
},
permissionErrorContainer: {
position: 'relative',
},
errorMessage: {
fontSize: theme.fontSizes.smallBody,
color: theme.palette.error.main,
position: 'absolute',
top: '-8px',
},
export const StyledForm = styled('form')(() => ({
display: 'flex',
flexDirection: 'column',
height: '100%',
}));
export const StyledContainer = styled('div')(() => ({
maxWidth: '400px',
}));
export const StyledDescription = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(1),
}));
export const StyledInput = styled(Input)(({ theme }) => ({
width: '100%',
marginBottom: theme.spacing(2),
}));
export const StyledTextField = styled(TextField)(({ theme }) => ({
width: '100%',
marginBottom: theme.spacing(2),
}));
export const StyledButtonContainer = styled('div')(() => ({
marginTop: 'auto',
display: 'flex',
justifyContent: 'flex-end',
}));
export const StyledButton = styled(Button)(({ theme }) => ({
marginLeft: theme.spacing(3),
}));

View File

@ -1,9 +1,14 @@
import Input from 'component/common/Input/Input';
import { TextField, Button } from '@mui/material';
import { useStyles } from './ProjectForm.styles';
import React from 'react';
import { trim } from 'component/common/util';
import {
StyledForm,
StyledContainer,
StyledDescription,
StyledInput,
StyledTextField,
StyledButtonContainer,
StyledButton,
} from './ProjectForm.styles';
interface IProjectForm {
projectId: string;
projectName: string;
@ -34,16 +39,11 @@ const ProjectForm: React.FC<IProjectForm> = ({
validateProjectId,
clearErrors,
}) => {
const { classes: styles } = useStyles();
return (
<form onSubmit={handleSubmit} className={styles.form}>
<div className={styles.container}>
<p className={styles.inputDescription}>
What is your project Id?
</p>
<Input
className={styles.input}
<StyledForm onSubmit={handleSubmit}>
<StyledContainer>
<StyledDescription>What is your project Id?</StyledDescription>
<StyledInput
label="Project Id"
value={projectId}
onChange={e => setProjectId(trim(e.target.value))}
@ -56,11 +56,10 @@ const ProjectForm: React.FC<IProjectForm> = ({
required
/>
<p className={styles.inputDescription}>
<StyledDescription>
What is your project name?
</p>
<Input
className={styles.input}
</StyledDescription>
<StyledInput
label="Project name"
value={projectName}
onChange={e => setProjectName(e.target.value)}
@ -70,11 +69,10 @@ const ProjectForm: React.FC<IProjectForm> = ({
required
/>
<p className={styles.inputDescription}>
<StyledDescription>
What is your project description?
</p>
<TextField
className={styles.input}
</StyledDescription>
<StyledTextField
label="Project description"
variant="outlined"
multiline
@ -82,15 +80,13 @@ const ProjectForm: React.FC<IProjectForm> = ({
value={projectDesc}
onChange={e => setProjectDesc(e.target.value)}
/>
</div>
</StyledContainer>
<div className={styles.buttonContainer}>
<StyledButtonContainer>
{children}
<Button onClick={handleCancel} className={styles.cancelButton}>
Cancel
</Button>
</div>
</form>
<StyledButton onClick={handleCancel}>Cancel</StyledButton>
</StyledButtonContainer>
</StyledForm>
);
};

View File

@ -1,85 +1,83 @@
import { makeStyles } from 'tss-react/mui';
import { Link } from 'react-router-dom';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { flexRow } from 'themes/themeStyles';
import { styled } from '@mui/material';
export const useStyles = makeStyles()(theme => ({
projectInfo: {
width: '225px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
boxShadow: 'none',
[theme.breakpoints.down('md')]: {
flexDirection: 'row',
alignItems: 'stretch',
width: '100%',
marginBottom: '1rem',
},
},
percentageContainer: {
display: 'flex',
justifyContent: 'center',
margin: '1rem 0',
},
projectIcon: {
margin: '2rem 0',
[theme.breakpoints.down('md')]: {
margin: '0 0 0.25rem 0',
width: '53px',
},
},
subtitle: {
marginBottom: '1rem',
},
emphazisedText: {
fontSize: '1.5rem',
marginBottom: '1rem',
[theme.breakpoints.down('md')]: {
fontSize: '1rem',
marginBottom: '2rem',
},
},
infoSection: {
margin: '0',
textAlign: 'center',
marginBottom: '1rem',
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadiusLarge,
export const StyledDivContainer = styled('div')(({ theme }) => ({
...flexRow,
width: '225px',
flexDirection: 'column',
boxShadow: 'none',
[theme.breakpoints.down('md')]: {
flexDirection: 'row',
alignItems: 'stretch',
width: '100%',
padding: '1.5rem 1rem 1.5rem 1rem',
[theme.breakpoints.down('md')]: {
margin: '0 0.25rem',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
fontSize: '0.8rem',
position: 'relative',
padding: '0.8rem',
'&:first-of-type': {
marginLeft: '0',
},
'&:last-of-type': {
marginRight: '0',
},
marginBottom: theme.spacing(2),
},
}));
export const StyledDivPercentageContainer = styled('div')(({ theme }) => ({
display: 'flex',
justifyContent: 'center',
margin: theme.spacing(2, 0),
}));
export const StyledDivInfoContainer = styled('div')(({ theme }) => ({
margin: '0',
textAlign: 'center',
marginBottom: theme.spacing(2),
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadiusLarge,
width: '100%',
padding: theme.spacing(3, 2, 3, 2),
[theme.breakpoints.down('md')]: {
margin: theme.spacing(0, 0.5),
...flexRow,
flexDirection: 'column',
justifyContent: 'center',
fontSize: theme.fontSizes.smallBody,
position: 'relative',
padding: theme.spacing(1.5),
'&:first-of-type': {
marginLeft: '0',
},
},
arrowIcon: {
color: '#635dc5',
marginLeft: '0.5rem',
},
permissionButtonShortDesc: {
transform: `translateY(-10px)`,
},
infoLink: {
textDecoration: 'none',
color: '#635dc5',
[theme.breakpoints.down('md')]: {
position: 'absolute',
bottom: '5px',
},
},
linkText: {
[theme.breakpoints.down('md')]: {
display: 'none',
'&:last-of-type': {
marginRight: '0',
},
},
}));
export const StyledParagraphSubtitle = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(2),
}));
export const StyledParagraphEmphasizedText = styled('p')(({ theme }) => ({
fontSize: '1.5rem',
marginBottom: theme.spacing(2),
[theme.breakpoints.down('md')]: {
fontSize: theme.fontSizes.bodySize,
marginBottom: theme.spacing(4),
},
}));
export const StyledSpanLinkText = styled('p')(({ theme }) => ({
[theme.breakpoints.down('md')]: {
display: 'none',
},
}));
export 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),
},
}));
export const StyledArrowIcon = styled(ArrowForwardIcon)(({ theme }) => ({
color: theme.palette.primary.main,
marginLeft: theme.spacing(1),
}));

View File

@ -1,14 +1,18 @@
import { useStyles } from './ProjectInfo.styles';
import { Link } from 'react-router-dom';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import classnames from 'classnames';
import { useThemeStyles } from 'themes/themeStyles';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { DEFAULT_PROJECT_ID } from '../../../../hooks/api/getters/useDefaultProject/useDefaultProjectId';
import {
StyledDivContainer,
StyledDivInfoContainer,
StyledDivPercentageContainer,
StyledParagraphSubtitle,
StyledParagraphEmphasizedText,
StyledLink,
StyledSpanLinkText,
StyledArrowIcon,
} from './ProjectInfo.styles';
interface IProjectInfoProps {
id: string;
@ -19,8 +23,6 @@ interface IProjectInfoProps {
}
const ProjectInfo = ({ id, memberCount, health }: IProjectInfoProps) => {
const { classes: themeStyles } = useThemeStyles();
const { classes: styles } = useStyles();
const { uiConfig } = useUiConfig();
let link = `/admin/users`;
@ -31,69 +33,44 @@ const ProjectInfo = ({ id, memberCount, health }: IProjectInfoProps) => {
return (
<aside>
<div className={styles.projectInfo}>
<div className={styles.infoSection}>
<div data-loading className={styles.percentageContainer}>
<StyledDivContainer>
<StyledDivInfoContainer>
<StyledDivPercentageContainer>
<PercentageCircle percentage={health} />
</div>
<p className={styles.subtitle} data-loading>
</StyledDivPercentageContainer>
<StyledParagraphSubtitle data-loading>
Overall health rating
</p>
<p className={styles.emphazisedText} data-loading>
</StyledParagraphSubtitle>
<StyledParagraphEmphasizedText data-loading>
{health}%
</p>
<Link
data-loading
className={classnames(
themeStyles.flexRow,
themeStyles.justifyCenter,
styles.infoLink
)}
to={`/projects/${id}/health`}
>
<span className={styles.linkText} data-loading>
</StyledParagraphEmphasizedText>
<StyledLink data-loading to={`/projects/${id}/health`}>
<StyledSpanLinkText data-loading>
view more{' '}
</span>
<ArrowForwardIcon
data-loading
className={styles.arrowIcon}
/>
</Link>
</div>
</StyledSpanLinkText>
<StyledArrowIcon data-loading />
</StyledLink>
</StyledDivInfoContainer>
<ConditionallyRender
condition={id !== DEFAULT_PROJECT_ID}
show={
<div
className={styles.infoSection}
style={{ marginBottom: '0' }}
>
<p className={styles.subtitle} data-loading>
<StyledDivInfoContainer style={{ marginBottom: '0' }}>
<StyledParagraphSubtitle data-loading>
Project members
</p>
<p data-loading className={styles.emphazisedText}>
</StyledParagraphSubtitle>
<StyledParagraphEmphasizedText data-loading>
{memberCount}
</p>
<Link
data-loading
className={classnames(
themeStyles.flexRow,
themeStyles.justifyCenter,
styles.infoLink
)}
to={link}
>
<span className={styles.linkText} data-loading>
</StyledParagraphEmphasizedText>
<StyledLink data-loading to={link}>
<StyledSpanLinkText data-loading>
view more{' '}
</span>
<ArrowForwardIcon
data-loading
className={styles.arrowIcon}
/>
</Link>
</div>
</StyledSpanLinkText>
<StyledArrowIcon data-loading />
</StyledLink>
</StyledDivInfoContainer>
}
/>
</div>
</StyledDivContainer>
</aside>
);
};

View File

@ -1,63 +1,76 @@
import { makeStyles } from 'tss-react/mui';
import { styled } from '@mui/material';
import { Card, Box } from '@mui/material';
import { Delete, Edit } from '@mui/icons-material';
import { ReactComponent as ProjectIcon } from 'assets/icons/projectIcon.svg';
import { flexRow } from 'themes/themeStyles';
export const useStyles = makeStyles()(theme => ({
projectCard: {
padding: theme.spacing(1, 2, 2, 2),
width: '220px',
height: '204px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
margin: '0.5rem',
boxShadow: 'none',
border: '1px solid #efefef',
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
'&:hover': {
transition: 'background-color 0.2s ease-in-out',
backgroundColor: theme.palette.projectCard.hover,
},
export const StyledProjectCard = styled(Card)(({ theme }) => ({
padding: theme.spacing(1, 2, 2, 2),
width: '220px',
height: '204px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
margin: theme.spacing(1),
boxShadow: 'none',
border: `1px solid ${theme.palette.tertiary.contrast}`,
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
header: {
display: 'flex',
alignItems: 'center',
},
title: {
fontWeight: 'normal',
fontSize: '1rem',
lineClamp: 2,
display: '-webkit-box',
boxOrient: 'vertical',
textOverflow: 'ellipsis',
overflow: 'hidden',
alignItems: 'flex-start',
},
projectIcon: {
margin: '1rem auto',
width: '80px',
display: 'block',
},
info: {
display: 'flex',
justifyContent: 'space-between',
fontSize: '0.8rem',
},
infoBox: {
textAlign: 'center',
},
infoStats: {
color: theme.palette.projectCard.textColor,
fontWeight: 'bold',
},
actionsBtn: {
transform: 'translateX(15px)',
marginLeft: 'auto',
marginRight: theme.spacing(1),
},
icon: {
color: theme.palette.grey[700],
marginRight: '0.5rem',
'&:hover': {
transition: 'background-color 0.2s ease-in-out',
backgroundColor: theme.palette.projectCard.hover,
},
}));
export const StyledDivHeader = styled('div')(() => ({
...flexRow,
width: '100%',
}));
export const StyledH2Title = styled('h2')(({ theme }) => ({
fontWeight: 'normal',
fontSize: theme.fontSizes.bodySize,
lineClamp: 2,
display: '-webkit-box',
boxOrient: 'vertical',
textOverflow: 'ellipsis',
overflow: 'hidden',
alignItems: 'flex-start',
}));
export const StyledBox = styled(Box)(() => ({
...flexRow,
marginRight: 'auto',
}));
export const StyledEditIcon = styled(Edit)(({ theme }) => ({
color: theme.palette.neutral.main,
marginRight: theme.spacing(1),
}));
export const StyledDeleteIcon = styled(Delete)(({ theme }) => ({
color: theme.palette.neutral.main,
marginRight: theme.spacing(1),
}));
export const StyledProjectIcon = styled(ProjectIcon)(({ theme }) => ({
margin: theme.spacing(2, 'auto'),
width: '80px',
display: 'block',
}));
export const StyledDivInfo = styled('div')(({ theme }) => ({
display: 'flex',
justifyContent: 'space-between',
fontSize: theme.fontSizes.smallerBody,
}));
export const StyledDivInfoContainer = styled('div')(() => ({
textAlign: 'center',
}));
export const StyledParagraphInfo = styled('p')(({ theme }) => ({
color: theme.palette.projectCard.textColor,
fontWeight: 'bold',
}));

View File

@ -1,10 +1,7 @@
import { Card, Menu, MenuItem } from '@mui/material';
import { useStyles } from './ProjectCard.styles';
import { Menu, MenuItem } from '@mui/material';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import { ReactComponent as ProjectIcon } from 'assets/icons/projectIcon.svg';
import React, { SyntheticEvent, useContext, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Delete, Edit } from '@mui/icons-material';
import { getProjectEditPath } from 'utils/routePathHelpers';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
import {
@ -19,6 +16,20 @@ import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { FavoriteIconButton } from 'component/common/FavoriteIconButton/FavoriteIconButton';
import { DeleteProjectDialogue } from '../Project/DeleteProject/DeleteProjectDialogue';
import { styled } from '@mui/material';
import { flexRow } from 'themes/themeStyles';
import {
StyledProjectCard,
StyledDivHeader,
StyledBox,
StyledH2Title,
StyledEditIcon,
StyledDeleteIcon,
StyledProjectIcon,
StyledDivInfo,
StyledDivInfoContainer,
StyledParagraphInfo,
} from './ProjectCard.styles';
interface IProjectCardProps {
name: string;
@ -39,9 +50,8 @@ export const ProjectCard = ({
id,
isFavorite = false,
}: IProjectCardProps) => {
const { classes } = useStyles();
const { hasAccess } = useContext(AccessContext);
const { isOss, uiConfig } = useUiConfig();
const { isOss } = useUiConfig();
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
const [showDelDialog, setShowDelDialog] = useState(false);
const navigate = useNavigate();
@ -67,17 +77,20 @@ export const ProjectCard = ({
};
return (
<Card className={classes.projectCard} onMouseEnter={onHover}>
<div className={classes.header} data-loading>
<FavoriteIconButton
onClick={onFavorite}
isFavorite={isFavorite}
size="medium"
sx={{ ml: -1 }}
/>
<h2 className={classes.title}>{name}</h2>
<StyledProjectCard onMouseEnter={onHover}>
<StyledDivHeader data-loading>
<StyledBox>
<FavoriteIconButton
onClick={onFavorite}
isFavorite={isFavorite}
size="medium"
sx={{ ml: -1 }}
/>
<StyledH2Title>{name}</StyledH2Title>
</StyledBox>
<PermissionIconButton
style={{ transform: 'translateX(7px)' }}
permission={UPDATE_PROJECT}
hidden={isOss()}
projectId={id}
@ -85,7 +98,6 @@ export const ProjectCard = ({
onClick={handleClick}
tooltipProps={{
title: 'Options',
className: classes.actionsBtn,
}}
>
<MoreVertIcon />
@ -110,7 +122,7 @@ export const ProjectCard = ({
navigate(getProjectEditPath(id));
}}
>
<Edit className={classes.icon} />
<StyledEditIcon />
Edit project
</MenuItem>
<MenuItem
@ -120,42 +132,42 @@ export const ProjectCard = ({
}}
disabled={!canDeleteProject}
>
<Delete className={classes.icon} />
<StyledDeleteIcon />
{id === DEFAULT_PROJECT_ID && !canDeleteProject
? "You can't delete the default project"
: 'Delete project'}
</MenuItem>
</Menu>
</div>
</StyledDivHeader>
<div data-loading>
<ProjectIcon className={classes.projectIcon} />
<StyledProjectIcon />
</div>
<div className={classes.info}>
<div className={classes.infoBox}>
<p className={classes.infoStats} data-loading>
<StyledDivInfo>
<StyledDivInfoContainer>
<StyledParagraphInfo data-loading>
{featureCount}
</p>
</StyledParagraphInfo>
<p data-loading>toggles</p>
</div>
<div className={classes.infoBox}>
<p className={classes.infoStats} data-loading>
</StyledDivInfoContainer>
<StyledDivInfoContainer>
<StyledParagraphInfo data-loading>
{health}%
</p>
</StyledParagraphInfo>
<p data-loading>health</p>
</div>
</StyledDivInfoContainer>
<ConditionallyRender
condition={id !== DEFAULT_PROJECT_ID}
show={
<div className={classes.infoBox}>
<p className={classes.infoStats} data-loading>
<StyledDivInfoContainer>
<StyledParagraphInfo data-loading>
{memberCount}
</p>
</StyledParagraphInfo>
<p data-loading>members</p>
</div>
</StyledDivInfoContainer>
}
/>
</div>
</StyledDivInfo>
<DeleteProjectDialogue
project={id}
open={showDelDialog}
@ -164,6 +176,6 @@ export const ProjectCard = ({
setShowDelDialog(false);
}}
/>
</Card>
</StyledProjectCard>
);
};

View File

@ -1,24 +0,0 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
},
apiError: {
maxWidth: '400px',
marginBottom: '1rem',
},
cardLink: {
color: 'inherit',
textDecoration: 'none',
border: 'none',
padding: '0',
background: 'transparent',
fontFamily: theme.typography.fontFamily,
pointer: 'cursor',
},
}));

View File

@ -1,6 +1,5 @@
import { useMemo, useState } from 'react';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useStyles } from './ProjectEnvironment.styles';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
@ -38,6 +37,19 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
marginBottom: theme.spacing(4),
}));
const StyledDivContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexWrap: 'wrap',
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
}));
const StyledApiError = styled(ApiError)(({ theme }) => ({
maxWidth: '400px',
marginBottom: theme.spacing(2),
}));
const ProjectEnvironmentList = () => {
const projectId = useRequiredPathParam('projectId');
const projectName = useProjectNameOrId(projectId);
@ -56,7 +68,6 @@ const ProjectEnvironmentList = () => {
const [selectedEnvironment, setSelectedEnvironment] =
useState<IProjectEnvironment>();
const [hideDialog, setHideDialog] = useState(false);
const { classes: styles } = useStyles();
const { isOss } = useUiConfig();
const projectEnvironments = useMemo<IProjectEnvironment[]>(
@ -77,9 +88,8 @@ const ProjectEnvironmentList = () => {
const renderError = () => {
return (
<ApiError
<StyledApiError
onClick={refetch}
className={styles.apiError}
text="Error fetching environments"
/>
);
@ -229,7 +239,7 @@ const ProjectEnvironmentList = () => {
<ConditionallyRender
condition={uiConfig.flags.E}
show={
<div className={styles.container}>
<StyledDivContainer>
<ConditionallyRender
condition={Boolean(error)}
show={renderError()}
@ -305,7 +315,7 @@ const ProjectEnvironmentList = () => {
setOpen={setHideDialog}
onConfirm={onHideConfirm}
/>
</div>
</StyledDivContainer>
}
elseShow={
<Alert security="success">

View File

@ -1,24 +0,0 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
},
apiError: {
maxWidth: '400px',
marginBottom: '1rem',
},
cardLink: {
color: 'inherit',
textDecoration: 'none',
border: 'none',
padding: '0',
background: 'transparent',
fontFamily: theme.typography.fontFamily,
pointer: 'cursor',
},
}));

View File

@ -5,7 +5,6 @@ import { getProjectFetcher } from 'hooks/api/getters/useProject/getProjectFetche
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { ProjectCard } from '../ProjectCard/ProjectCard';
import { useStyles } from './ProjectList.styles';
import { IProjectCard } from 'interfaces/project';
import loadingData from './loadingData';
import { PageContent } from 'component/common/PageContent/PageContent';
@ -17,7 +16,7 @@ import { Add } from '@mui/icons-material';
import ApiError from 'component/common/ApiError/ApiError';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { TablePlaceholder } from 'component/common/Table';
import { useMediaQuery } from '@mui/material';
import { useMediaQuery, styled } from '@mui/material';
import theme from 'themes/theme';
import { Search } from 'component/common/Search/Search';
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
@ -25,6 +24,29 @@ import { ITooltipResolverProps } from 'component/common/TooltipResolver/TooltipR
import { ReactComponent as ProPlanIcon } from 'assets/icons/pro-enterprise-feature-badge.svg';
import { safeRegExp } from '@server/util/escape-regex';
const StyledDivContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexWrap: 'wrap',
[theme.breakpoints.down('sm')]: {
justifyContent: 'center',
},
}));
const StyledApiError = styled(ApiError)(({ theme }) => ({
maxWidth: '400px',
marginBottom: theme.spacing(2),
}));
const StyledCardLink = styled(Link)(({ theme }) => ({
color: 'inherit',
textDecoration: 'none',
border: 'none',
padding: '0',
background: 'transparent',
fontFamily: theme.typography.fontFamily,
pointer: 'cursor',
}));
type PageQueryType = Partial<Record<'search', string>>;
type projectMap = {
@ -71,7 +93,6 @@ function resolveCreateButtonData(
export const ProjectListNew = () => {
const { hasAccess } = useContext(AccessContext);
const navigate = useNavigate();
const { classes: styles } = useStyles();
const { projects, loading, error, refetch } = useProjects();
const [fetchedProjects, setFetchedProjects] = useState<projectMap>({});
const { isOss } = useUiConfig();
@ -127,11 +148,7 @@ export const ProjectListNew = () => {
const renderError = () => {
return (
<ApiError
onClick={refetch}
className={styles.apiError}
text="Error fetching projects"
/>
<StyledApiError onClick={refetch} text="Error fetching projects" />
);
};
@ -187,7 +204,7 @@ export const ProjectListNew = () => {
}
>
<ConditionallyRender condition={error} show={renderError()} />
<div className={styles.container}>
<StyledDivContainer>
<ConditionallyRender
condition={filteredProjects.length < 1 && !loading}
show={
@ -227,10 +244,9 @@ export const ProjectListNew = () => {
elseShow={() =>
filteredProjects.map(
(project: IProjectCard) => (
<Link
<StyledCardLink
key={project.id}
to={`/projects/${project.id}`}
className={styles.cardLink}
>
<ProjectCard
onHover={() =>
@ -247,14 +263,14 @@ export const ProjectListNew = () => {
}
isFavorite={project.favorite}
/>
</Link>
</StyledCardLink>
)
)
}
/>
}
/>
</div>
</StyledDivContainer>
</PageContent>
);
};

View File

@ -1,12 +0,0 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
deleteInput: {
marginTop: '1rem',
},
link: {
textDecoration: 'none',
color: theme.palette.primary.main,
fontWeight: theme.fontWeight.bold,
},
}));

View File

@ -1,9 +1,13 @@
import React, { useState } from 'react';
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import Input from 'component/common/Input/Input';
import { useStyles } from './SegmentDeleteConfirm.styles';
import { ISegment } from 'interfaces/segment';
import { SEGMENT_DIALOG_NAME_ID } from 'utils/testIds';
import { styled } from '@mui/material';
const StyledInput = styled(Input)(({ theme }) => ({
marginTop: theme.spacing(2),
}));
interface ISegmentDeleteConfirmProps {
segment: ISegment;
@ -18,7 +22,6 @@ export const SegmentDeleteConfirm = ({
onClose,
onRemove,
}: ISegmentDeleteConfirmProps) => {
const { classes: styles } = useStyles();
const [confirmName, setConfirmName] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
@ -49,12 +52,11 @@ export const SegmentDeleteConfirm = ({
</p>
<form id={formId}>
<Input
<StyledInput
autoFocus
onChange={handleChange}
value={confirmName}
label="Segment name"
className={styles.deleteInput}
data-testid={SEGMENT_DIALOG_NAME_ID}
/>
</form>

View File

@ -1,5 +1,4 @@
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import { useStyles } from '../SegmentDeleteConfirm/SegmentDeleteConfirm.styles';
import { ISegment } from 'interfaces/segment';
import { IFeatureStrategy } from 'interfaces/strategy';
import { Link } from 'react-router-dom';
@ -11,6 +10,12 @@ const StyledUl = styled('ul')({
marginBottom: 0,
});
const StyledLink = styled(Link)(({ theme }) => ({
textDecoration: 'none',
color: theme.palette.primary.main,
fontWeight: theme.fontWeight.bold,
}));
interface ISegmentDeleteUsedSegmentProps {
segment: ISegment;
open: boolean;
@ -24,8 +29,6 @@ export const SegmentDeleteUsedSegment = ({
onClose,
strategies,
}: ISegmentDeleteUsedSegmentProps) => {
const { classes: styles } = useStyles();
return (
<Dialogue
title="You can't delete a segment that's currently in use"
@ -40,7 +43,7 @@ export const SegmentDeleteUsedSegment = ({
<StyledUl>
{strategies?.map(strategy => (
<li key={strategy.id}>
<Link
<StyledLink
to={formatEditStrategyPath(
strategy.projectId!,
strategy.featureName!,
@ -49,11 +52,10 @@ export const SegmentDeleteUsedSegment = ({
)}
target="_blank"
rel="noopener noreferrer"
className={styles.link}
>
{strategy.featureName!}{' '}
{formatStrategyNameParens(strategy)}
</Link>
</StyledLink>
</li>
))}
</StyledUl>