mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
refactor: batch of changes for styled components (#2791)
This commit is contained in:
parent
5fe16207db
commit
231b26995c
@ -1,9 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
label: {
|
|
||||||
display: 'inline-flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
}));
|
|
@ -8,12 +8,12 @@ import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
|||||||
import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { useStyles } from './FeatureOverviewEnvSwitch.styles';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { useChangeRequestToggle } from 'hooks/useChangeRequestToggle';
|
import { useChangeRequestToggle } from 'hooks/useChangeRequestToggle';
|
||||||
import { ChangeRequestDialogue } from 'component/changeRequest/ChangeRequestConfirmDialog/ChangeRequestConfirmDialog';
|
import { ChangeRequestDialogue } from 'component/changeRequest/ChangeRequestConfirmDialog/ChangeRequestConfirmDialog';
|
||||||
import { UpdateEnabledMessage } from '../../../../../changeRequest/ChangeRequestConfirmDialog/ChangeRequestMessages/UpdateEnabledMessage';
|
import { UpdateEnabledMessage } from '../../../../../changeRequest/ChangeRequestConfirmDialog/ChangeRequestMessages/UpdateEnabledMessage';
|
||||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
interface IFeatureOverviewEnvSwitchProps {
|
interface IFeatureOverviewEnvSwitchProps {
|
||||||
env: IFeatureEnvironment;
|
env: IFeatureEnvironment;
|
||||||
@ -22,6 +22,12 @@ interface IFeatureOverviewEnvSwitchProps {
|
|||||||
showInfoBox: () => void;
|
showInfoBox: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledLabel = styled('label')({
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
});
|
||||||
|
|
||||||
const FeatureOverviewEnvSwitch = ({
|
const FeatureOverviewEnvSwitch = ({
|
||||||
env,
|
env,
|
||||||
callback,
|
callback,
|
||||||
@ -34,7 +40,6 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
useFeatureApi();
|
useFeatureApi();
|
||||||
const { refetchFeature } = useFeature(projectId, featureId);
|
const { refetchFeature } = useFeature(projectId, featureId);
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
||||||
const {
|
const {
|
||||||
onChangeRequestToggle,
|
onChangeRequestToggle,
|
||||||
@ -110,7 +115,7 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className={styles.label}>
|
<StyledLabel>
|
||||||
<PermissionSwitch
|
<PermissionSwitch
|
||||||
permission={UPDATE_FEATURE_ENVIRONMENT}
|
permission={UPDATE_FEATURE_ENVIRONMENT}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -119,7 +124,7 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
environmentId={env.name}
|
environmentId={env.name}
|
||||||
/>
|
/>
|
||||||
{content}
|
{content}
|
||||||
</label>
|
</StyledLabel>
|
||||||
<ChangeRequestDialogue
|
<ChangeRequestDialogue
|
||||||
isOpen={changeRequestDialogDetails.isOpen}
|
isOpen={changeRequestDialogDetails.isOpen}
|
||||||
onClose={onChangeRequestToggleClose}
|
onClose={onChangeRequestToggleClose}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
accordionBodyInnerContainer: {
|
|
||||||
[theme.breakpoints.down(400)]: {
|
|
||||||
padding: '0.5rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
accordionBody: {
|
|
||||||
width: '100%',
|
|
||||||
position: 'relative',
|
|
||||||
paddingBottom: '1rem',
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,5 +1,5 @@
|
|||||||
import { DragEventHandler, RefObject, useEffect, useState } from 'react';
|
import { DragEventHandler, RefObject, useEffect, useState } from 'react';
|
||||||
import { Alert } from '@mui/material';
|
import { Alert, styled } from '@mui/material';
|
||||||
import useFeatureStrategyApi from 'hooks/api/actions/useFeatureStrategyApi/useFeatureStrategyApi';
|
import useFeatureStrategyApi from 'hooks/api/actions/useFeatureStrategyApi/useFeatureStrategyApi';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
@ -8,7 +8,6 @@ import { StrategyDraggableItem } from './StrategyDraggableItem/StrategyDraggable
|
|||||||
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
||||||
import { FeatureStrategyEmpty } from 'component/feature/FeatureStrategy/FeatureStrategyEmpty/FeatureStrategyEmpty';
|
import { FeatureStrategyEmpty } from 'component/feature/FeatureStrategy/FeatureStrategyEmpty/FeatureStrategyEmpty';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { useStyles } from './EnvironmentAccordionBody.styles';
|
|
||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
|
|
||||||
interface IEnvironmentAccordionBodyProps {
|
interface IEnvironmentAccordionBodyProps {
|
||||||
@ -17,6 +16,18 @@ interface IEnvironmentAccordionBodyProps {
|
|||||||
otherEnvironments?: IFeatureEnvironment['name'][];
|
otherEnvironments?: IFeatureEnvironment['name'][];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledAccordionBody = styled('div')(({ theme }) => ({
|
||||||
|
width: '100%',
|
||||||
|
position: 'relative',
|
||||||
|
paddingBottom: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordionBodyInnerContainer = styled('div')(({ theme }) => ({
|
||||||
|
[theme.breakpoints.down(400)]: {
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const EnvironmentAccordionBody = ({
|
const EnvironmentAccordionBody = ({
|
||||||
featureEnvironment,
|
featureEnvironment,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
@ -35,7 +46,6 @@ const EnvironmentAccordionBody = ({
|
|||||||
index: number;
|
index: number;
|
||||||
height: number;
|
height: number;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Use state to enable drag and drop, but switch to API output when it arrives
|
// Use state to enable drag and drop, but switch to API output when it arrives
|
||||||
setStrategies(featureEnvironment?.strategies || []);
|
setStrategies(featureEnvironment?.strategies || []);
|
||||||
@ -128,8 +138,8 @@ const EnvironmentAccordionBody = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.accordionBody}>
|
<StyledAccordionBody>
|
||||||
<div className={styles.accordionBodyInnerContainer}>
|
<StyledAccordionBodyInnerContainer>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={strategies.length > 0 && isDisabled}
|
condition={strategies.length > 0 && isDisabled}
|
||||||
show={() => (
|
show={() => (
|
||||||
@ -166,8 +176,8 @@ const EnvironmentAccordionBody = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledAccordionBodyInnerContainer>
|
||||||
</div>
|
</StyledAccordionBody>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,20 +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.divider}`,
|
|
||||||
},
|
|
||||||
chip: {
|
|
||||||
margin: '0.25rem',
|
|
||||||
},
|
|
||||||
paragraph: {
|
|
||||||
display: 'inline',
|
|
||||||
margin: '0.25rem 0',
|
|
||||||
maxWidth: '95%',
|
|
||||||
textAlign: 'center',
|
|
||||||
wordBreak: 'break-word',
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,6 +1,5 @@
|
|||||||
import { Chip } from '@mui/material';
|
import { Chip, styled } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { useStyles } from './ConstraintItem.styles';
|
|
||||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
|
|
||||||
interface IConstraintItemProps {
|
interface IConstraintItemProps {
|
||||||
@ -8,22 +7,40 @@ interface IConstraintItemProps {
|
|||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
|
width: '100%',
|
||||||
|
padding: theme.spacing(2, 3),
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
border: `1px solid ${theme.palette.divider}`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledParagraph = styled('p')(({ theme }) => ({
|
||||||
|
display: 'inline',
|
||||||
|
margin: theme.spacing(0.5, 0),
|
||||||
|
maxWidth: '95%',
|
||||||
|
textAlign: 'center',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledChip = styled(Chip)(({ theme }) => ({
|
||||||
|
margin: theme.spacing(0.5),
|
||||||
|
}));
|
||||||
|
|
||||||
export const ConstraintItem = ({ value, text }: IConstraintItemProps) => {
|
export const ConstraintItem = ({ value, text }: IConstraintItemProps) => {
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<StyledContainer>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={value.length === 0}
|
condition={value.length === 0}
|
||||||
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) => (
|
{value.map((v: string) => (
|
||||||
<Chip
|
<StyledChip
|
||||||
key={v}
|
key={v}
|
||||||
label={
|
label={
|
||||||
<StringTruncator
|
<StringTruncator
|
||||||
@ -32,12 +49,11 @@ export const ConstraintItem = ({ value, text }: IConstraintItemProps) => {
|
|||||||
maxLength={50}
|
maxLength={50}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
className={styles.chip}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
valueContainer: {
|
|
||||||
padding: theme.spacing(2, 3),
|
|
||||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
|
||||||
borderRadius: theme.shape.borderRadiusMedium,
|
|
||||||
},
|
|
||||||
valueSeparator: {
|
|
||||||
color: theme.palette.grey[700],
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,6 +1,6 @@
|
|||||||
import { Fragment, useMemo, VFC } from 'react';
|
import { Fragment, useMemo, VFC } from 'react';
|
||||||
import { Box, Chip } from '@mui/material';
|
import { Box, Chip, styled } from '@mui/material';
|
||||||
import { IFeatureStrategy, IFeatureStrategyPayload } from 'interfaces/strategy';
|
import { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
@ -10,7 +10,6 @@ import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { FeatureOverviewSegment } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSegment/FeatureOverviewSegment';
|
import { FeatureOverviewSegment } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSegment/FeatureOverviewSegment';
|
||||||
import { ConstraintAccordionList } from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
import { ConstraintAccordionList } from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
||||||
import { useStyles } from './StrategyExecution.styles';
|
|
||||||
import {
|
import {
|
||||||
parseParameterNumber,
|
parseParameterNumber,
|
||||||
parseParameterString,
|
parseParameterString,
|
||||||
@ -28,11 +27,20 @@ const NoItems: VFC = () => (
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const StyledValueContainer = styled(Box)(({ theme }) => ({
|
||||||
|
padding: theme.spacing(2, 3),
|
||||||
|
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledValueSeparator = styled('span')(({ theme }) => ({
|
||||||
|
color: theme.palette.neutral.main,
|
||||||
|
}));
|
||||||
|
|
||||||
export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
||||||
strategy,
|
strategy,
|
||||||
}) => {
|
}) => {
|
||||||
const { parameters, constraints = [] } = strategy;
|
const { parameters, constraints = [] } = strategy;
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const { strategies } = useStrategies();
|
const { strategies } = useStrategies();
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const { segments } = useSegments();
|
const { segments } = useSegments();
|
||||||
@ -54,8 +62,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
const percentage = parseParameterNumber(parameters[key]);
|
const percentage = parseParameterNumber(parameters[key]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<StyledValueContainer
|
||||||
className={styles.valueContainer}
|
|
||||||
sx={{ display: 'flex', alignItems: 'center' }}
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<Box sx={{ mr: 2 }}>
|
<Box sx={{ mr: 2 }}>
|
||||||
@ -77,7 +84,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
: ''}{' '}
|
: ''}{' '}
|
||||||
is included.
|
is included.
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</StyledValueContainer>
|
||||||
);
|
);
|
||||||
case 'userIds':
|
case 'userIds':
|
||||||
case 'UserIds':
|
case 'UserIds':
|
||||||
@ -101,12 +108,12 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [parameters, definition, constraints, styles]);
|
}, [parameters, definition, constraints]);
|
||||||
|
|
||||||
const customStrategyList = useMemo(() => {
|
const customStrategyList = useMemo(() => {
|
||||||
if (!parameters || !definition?.editable) return null;
|
if (!parameters || !definition?.editable) return null;
|
||||||
const isSetTo = (
|
const isSetTo = (
|
||||||
<span className={styles.valueSeparator}>{' is set to '}</span>
|
<StyledValueSeparator>{' is set to '}</StyledValueSeparator>
|
||||||
);
|
);
|
||||||
|
|
||||||
return definition?.parameters.map(param => {
|
return definition?.parameters.map(param => {
|
||||||
@ -123,9 +130,9 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
const values = parseParameterStrings(parameters[name]);
|
const values = parseParameterStrings(parameters[name]);
|
||||||
|
|
||||||
return values.length > 0 ? (
|
return values.length > 0 ? (
|
||||||
<div className={styles.valueContainer}>
|
<StyledValueContainer>
|
||||||
{nameItem}{' '}
|
{nameItem}{' '}
|
||||||
<span className={styles.valueSeparator}>
|
<StyledValueSeparator>
|
||||||
has {values.length}{' '}
|
has {values.length}{' '}
|
||||||
{values.length > 1 ? `items` : 'item'}:{' '}
|
{values.length > 1 ? `items` : 'item'}:{' '}
|
||||||
{values.map((item: string) => (
|
{values.map((item: string) => (
|
||||||
@ -141,15 +148,14 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
sx={{ mr: 0.5 }}
|
sx={{ mr: 0.5 }}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</span>
|
</StyledValueSeparator>
|
||||||
</div>
|
</StyledValueContainer>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
case 'percentage':
|
case 'percentage':
|
||||||
const percentage = parseParameterNumber(parameters[name]);
|
const percentage = parseParameterNumber(parameters[name]);
|
||||||
return parameters[name] !== '' ? (
|
return parameters[name] !== '' ? (
|
||||||
<Box
|
<StyledValueContainer
|
||||||
className={styles.valueContainer}
|
|
||||||
sx={{ display: 'flex', alignItems: 'center' }}
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<Box sx={{ mr: 2 }}>
|
<Box sx={{ mr: 2 }}>
|
||||||
@ -168,13 +174,13 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
label={`${percentage}%`}
|
label={`${percentage}%`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</StyledValueContainer>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
return parameters[name] === 'true' ||
|
return parameters[name] === 'true' ||
|
||||||
parameters[name] === 'false' ? (
|
parameters[name] === 'false' ? (
|
||||||
<div className={styles.valueContainer}>
|
<StyledValueContainer>
|
||||||
<StringTruncator
|
<StringTruncator
|
||||||
maxLength={15}
|
maxLength={15}
|
||||||
maxWidth="150"
|
maxWidth="150"
|
||||||
@ -191,20 +197,20 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
size="small"
|
size="small"
|
||||||
label={parameters[name]}
|
label={parameters[name]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledValueContainer>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
case 'string':
|
case 'string':
|
||||||
const value = parseParameterString(parameters[name]);
|
const value = parseParameterString(parameters[name]);
|
||||||
return typeof parameters[name] !== 'undefined' ? (
|
return typeof parameters[name] !== 'undefined' ? (
|
||||||
<div className={styles.valueContainer}>
|
<StyledValueContainer>
|
||||||
{nameItem}
|
{nameItem}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={value === ''}
|
condition={value === ''}
|
||||||
show={
|
show={
|
||||||
<span className={styles.valueSeparator}>
|
<StyledValueSeparator>
|
||||||
{' is an empty string'}
|
{' is an empty string'}
|
||||||
</span>
|
</StyledValueSeparator>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<>
|
<>
|
||||||
@ -217,13 +223,13 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledValueContainer>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
case 'number':
|
case 'number':
|
||||||
const number = parseParameterNumber(parameters[name]);
|
const number = parseParameterNumber(parameters[name]);
|
||||||
return parameters[name] !== '' && number !== undefined ? (
|
return parameters[name] !== '' && number !== undefined ? (
|
||||||
<div className={styles.valueContainer}>
|
<StyledValueContainer>
|
||||||
{nameItem}
|
{nameItem}
|
||||||
{isSetTo}
|
{isSetTo}
|
||||||
<StringTruncator
|
<StringTruncator
|
||||||
@ -231,7 +237,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
text={String(number)}
|
text={String(number)}
|
||||||
maxLength={50}
|
maxLength={50}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledValueContainer>
|
||||||
) : null;
|
) : null;
|
||||||
case 'default':
|
case 'default':
|
||||||
return null;
|
return null;
|
||||||
@ -239,7 +245,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}, [parameters, definition, styles]);
|
}, [parameters, definition]);
|
||||||
|
|
||||||
if (!parameters) {
|
if (!parameters) {
|
||||||
return <NoItems />;
|
return <NoItems />;
|
||||||
@ -259,7 +265,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
),
|
),
|
||||||
strategy.name === 'default' && (
|
strategy.name === 'default' && (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ width: '100%' }} className={styles.valueContainer}>
|
<StyledValueContainer sx={{ width: '100%' }}>
|
||||||
The standard strategy is{' '}
|
The standard strategy is{' '}
|
||||||
<Chip
|
<Chip
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@ -268,7 +274,7 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
label="ON"
|
label="ON"
|
||||||
/>{' '}
|
/>{' '}
|
||||||
for all users.
|
for all users.
|
||||||
</Box>
|
</StyledValueContainer>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
...(parametersList ?? []),
|
...(parametersList ?? []),
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
featureOverviewEnvironment: {
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
backgroundColor: theme.palette.background.paper,
|
|
||||||
},
|
|
||||||
accordion: {
|
|
||||||
boxShadow: 'none',
|
|
||||||
background: 'none',
|
|
||||||
},
|
|
||||||
accordionHeader: {
|
|
||||||
boxShadow: 'none',
|
|
||||||
padding: '1rem 2rem',
|
|
||||||
[theme.breakpoints.down(400)]: {
|
|
||||||
padding: '0.5rem 1rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
accordionBodyInnerContainer: {
|
|
||||||
[theme.breakpoints.down(400)]: {
|
|
||||||
padding: '0.5rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
accordionDetails: {
|
|
||||||
padding: theme.spacing(3),
|
|
||||||
background: theme.palette.secondaryContainer,
|
|
||||||
borderBottomLeftRadius: theme.shape.borderRadiusLarge,
|
|
||||||
borderBottomRightRadius: theme.shape.borderRadiusLarge,
|
|
||||||
borderBottom: `4px solid ${theme.palette.primary.light}`,
|
|
||||||
|
|
||||||
[theme.breakpoints.down('md')]: {
|
|
||||||
padding: theme.spacing(2, 1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
accordionDetailsDisabled: {
|
|
||||||
borderBottom: `4px solid ${theme.palette.neutral.border}`,
|
|
||||||
},
|
|
||||||
accordionBody: {
|
|
||||||
width: '100%',
|
|
||||||
position: 'relative',
|
|
||||||
paddingBottom: theme.spacing(2),
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
headerTitle: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
[theme.breakpoints.down(560)]: {
|
|
||||||
flexDirection: 'column',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
headerIcon: {
|
|
||||||
[theme.breakpoints.down(560)]: {
|
|
||||||
marginBottom: '0.5rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
iconContainer: {
|
|
||||||
backgroundColor: theme.palette.primary.light,
|
|
||||||
borderRadius: '50%',
|
|
||||||
width: '28px',
|
|
||||||
height: '28px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
marginRight: '0.5rem',
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
fill: '#fff',
|
|
||||||
width: '17px',
|
|
||||||
height: '17px',
|
|
||||||
},
|
|
||||||
linkContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
marginBottom: '1rem',
|
|
||||||
},
|
|
||||||
truncator: {
|
|
||||||
fontSize: theme.fontSizes.bodySize,
|
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
|
||||||
[theme.breakpoints.down(560)]: {
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginLeft: '1.8rem',
|
|
||||||
[theme.breakpoints.down(560)]: {
|
|
||||||
flexDirection: 'column',
|
|
||||||
marginLeft: '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -4,9 +4,8 @@ import {
|
|||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
Box,
|
Box,
|
||||||
Chip,
|
Chip,
|
||||||
useTheme,
|
styled,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { ExpandMore } from '@mui/icons-material';
|
import { ExpandMore } from '@mui/icons-material';
|
||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
import useFeatureMetrics from 'hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
|
import useFeatureMetrics from 'hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
|
||||||
@ -15,7 +14,6 @@ import { getFeatureMetrics } from 'utils/getFeatureMetrics';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
||||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
import { useStyles } from './FeatureOverviewEnvironment.styles';
|
|
||||||
import EnvironmentAccordionBody from './EnvironmentAccordionBody/EnvironmentAccordionBody';
|
import EnvironmentAccordionBody from './EnvironmentAccordionBody/EnvironmentAccordionBody';
|
||||||
import { EnvironmentFooter } from './EnvironmentFooter/EnvironmentFooter';
|
import { EnvironmentFooter } from './EnvironmentFooter/EnvironmentFooter';
|
||||||
import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics';
|
import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics';
|
||||||
@ -23,17 +21,104 @@ import { FeatureStrategyMenu } from 'component/feature/FeatureStrategy/FeatureSt
|
|||||||
import { FEATURE_ENVIRONMENT_ACCORDION } from 'utils/testIds';
|
import { FEATURE_ENVIRONMENT_ACCORDION } from 'utils/testIds';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { FeatureStrategyIcons } from 'component/feature/FeatureStrategy/FeatureStrategyIcons/FeatureStrategyIcons';
|
import { FeatureStrategyIcons } from 'component/feature/FeatureStrategy/FeatureStrategyIcons/FeatureStrategyIcons';
|
||||||
// import { Badge } from 'component/common/Badge/Badge';
|
|
||||||
|
|
||||||
interface IFeatureOverviewEnvironmentProps {
|
interface IFeatureOverviewEnvironmentProps {
|
||||||
env: IFeatureEnvironment;
|
env: IFeatureEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledFeatureOverviewEnvironment = styled('div', {
|
||||||
|
shouldForwardProp: prop => prop !== 'enabled',
|
||||||
|
})<{ enabled: boolean }>(({ theme, enabled }) => ({
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
background: enabled
|
||||||
|
? theme.palette.background.paper
|
||||||
|
: theme.palette.neutral.light,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordion = styled(Accordion)({
|
||||||
|
boxShadow: 'none',
|
||||||
|
background: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
|
||||||
|
boxShadow: 'none',
|
||||||
|
padding: theme.spacing(2, 4),
|
||||||
|
[theme.breakpoints.down(400)]: {
|
||||||
|
padding: theme.spacing(1, 2),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordionDetails = styled(AccordionDetails, {
|
||||||
|
shouldForwardProp: prop => prop !== 'enabled',
|
||||||
|
})<{ enabled: boolean }>(({ theme, enabled }) => ({
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
background: theme.palette.secondaryContainer,
|
||||||
|
borderBottomLeftRadius: theme.shape.borderRadiusLarge,
|
||||||
|
borderBottomRightRadius: theme.shape.borderRadiusLarge,
|
||||||
|
borderBottom: `4px solid ${
|
||||||
|
enabled ? theme.palette.primary.light : theme.palette.neutral.border
|
||||||
|
}`,
|
||||||
|
|
||||||
|
[theme.breakpoints.down('md')]: {
|
||||||
|
padding: theme.spacing(2, 1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledEnvironmentAccordionBody = styled(EnvironmentAccordionBody)(
|
||||||
|
({ theme }) => ({
|
||||||
|
width: '100%',
|
||||||
|
position: 'relative',
|
||||||
|
paddingBottom: theme.spacing(2),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const StyledHeader = styled('div', {
|
||||||
|
shouldForwardProp: prop => prop !== 'enabled',
|
||||||
|
})<{ enabled: boolean }>(({ theme, enabled }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
color: enabled ? theme.palette.text.primary : theme.palette.text.secondary,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHeaderTitle = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledEnvironmentIcon = styled(EnvironmentIcon)(({ theme }) => ({
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
marginBottom: '0.5rem',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledStringTruncator = styled(StringTruncator)(({ theme }) => ({
|
||||||
|
fontSize: theme.fontSizes.bodySize,
|
||||||
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginLeft: '1.8rem',
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginLeft: '0',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const FeatureOverviewEnvironment = ({
|
const FeatureOverviewEnvironment = ({
|
||||||
env,
|
env,
|
||||||
}: IFeatureOverviewEnvironmentProps) => {
|
}: IFeatureOverviewEnvironmentProps) => {
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const theme = useTheme();
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const { metrics } = useFeatureMetrics(projectId, featureId);
|
const { metrics } = useFeatureMetrics(projectId, featureId);
|
||||||
@ -48,40 +133,19 @@ const FeatureOverviewEnvironment = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<StyledFeatureOverviewEnvironment enabled={env.enabled}>
|
||||||
className={styles.featureOverviewEnvironment}
|
<StyledAccordion
|
||||||
style={{
|
|
||||||
background: !env.enabled
|
|
||||||
? theme.palette.neutral.light
|
|
||||||
: theme.palette.background.paper,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Accordion
|
|
||||||
className={styles.accordion}
|
|
||||||
data-testid={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`}
|
data-testid={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`}
|
||||||
>
|
>
|
||||||
<AccordionSummary
|
<StyledAccordionSummary
|
||||||
className={styles.accordionHeader}
|
|
||||||
expandIcon={<ExpandMore titleAccess="Toggle" />}
|
expandIcon={<ExpandMore titleAccess="Toggle" />}
|
||||||
>
|
>
|
||||||
<div
|
<StyledHeader data-loading enabled={env.enabled}>
|
||||||
className={styles.header}
|
<StyledHeaderTitle>
|
||||||
data-loading
|
<StyledEnvironmentIcon enabled={env.enabled} />
|
||||||
style={{
|
|
||||||
color: !env.enabled
|
|
||||||
? theme.palette.text.secondary
|
|
||||||
: theme.palette.text.primary,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className={styles.headerTitle}>
|
|
||||||
<EnvironmentIcon
|
|
||||||
enabled={env.enabled}
|
|
||||||
className={styles.headerIcon}
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<StringTruncator
|
<StyledStringTruncator
|
||||||
text={env.name}
|
text={env.name}
|
||||||
className={styles.truncator}
|
|
||||||
maxWidth="100"
|
maxWidth="100"
|
||||||
maxLength={15}
|
maxLength={15}
|
||||||
/>
|
/>
|
||||||
@ -97,8 +161,8 @@ const FeatureOverviewEnvironment = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledHeaderTitle>
|
||||||
<div className={styles.container}>
|
<StyledContainer>
|
||||||
<FeatureStrategyMenu
|
<FeatureStrategyMenu
|
||||||
label="Add strategy"
|
label="Add strategy"
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -109,21 +173,17 @@ const FeatureOverviewEnvironment = ({
|
|||||||
<FeatureStrategyIcons
|
<FeatureStrategyIcons
|
||||||
strategies={featureEnvironment?.strategies}
|
strategies={featureEnvironment?.strategies}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledContainer>
|
||||||
</div>
|
</StyledHeader>
|
||||||
|
|
||||||
<FeatureOverviewEnvironmentMetrics
|
<FeatureOverviewEnvironmentMetrics
|
||||||
environmentMetric={environmentMetric}
|
environmentMetric={environmentMetric}
|
||||||
disabled={!env.enabled}
|
disabled={!env.enabled}
|
||||||
/>
|
/>
|
||||||
</AccordionSummary>
|
</StyledAccordionSummary>
|
||||||
|
|
||||||
<AccordionDetails
|
<StyledAccordionDetails enabled={env.enabled}>
|
||||||
className={classNames(styles.accordionDetails, {
|
<StyledEnvironmentAccordionBody
|
||||||
[styles.accordionDetailsDisabled]: !env.enabled,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<EnvironmentAccordionBody
|
|
||||||
featureEnvironment={featureEnvironment}
|
featureEnvironment={featureEnvironment}
|
||||||
isDisabled={!env.enabled}
|
isDisabled={!env.enabled}
|
||||||
otherEnvironments={feature?.environments
|
otherEnvironments={feature?.environments
|
||||||
@ -156,9 +216,9 @@ const FeatureOverviewEnvironment = ({
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</AccordionDetails>
|
</StyledAccordionDetails>
|
||||||
</Accordion>
|
</StyledAccordion>
|
||||||
</div>
|
</StyledFeatureOverviewEnvironment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
container: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
info: {
|
|
||||||
marginRight: '0.5rem',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
fill: theme.palette.grey[300],
|
|
||||||
height: '75px',
|
|
||||||
width: '75px',
|
|
||||||
[theme.breakpoints.down(500)]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
infoParagraph: {
|
|
||||||
maxWidth: '270px',
|
|
||||||
marginTop: '0.25rem',
|
|
||||||
fontSize: theme.fontSizes.smallBody,
|
|
||||||
textAlign: 'right',
|
|
||||||
[theme.breakpoints.down(700)]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
percentage: {
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
textAlign: 'right',
|
|
||||||
fontSize: theme.fontSizes.bodySize,
|
|
||||||
},
|
|
||||||
percentageCircle: {
|
|
||||||
margin: '0 1rem',
|
|
||||||
[theme.breakpoints.down(500)]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -3,19 +3,62 @@ import { useTheme } from '@mui/system';
|
|||||||
import { IFeatureEnvironmentMetrics } from 'interfaces/featureToggle';
|
import { IFeatureEnvironmentMetrics } from 'interfaces/featureToggle';
|
||||||
import { calculatePercentage } from 'utils/calculatePercentage';
|
import { calculatePercentage } from 'utils/calculatePercentage';
|
||||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
import { useStyles } from './FeatureOverviewEnvironmentMetrics.styles';
|
|
||||||
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
||||||
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
interface IFeatureOverviewEnvironmentMetrics {
|
interface IFeatureOverviewEnvironmentMetrics {
|
||||||
environmentMetric?: IFeatureEnvironmentMetrics;
|
environmentMetric?: IFeatureEnvironmentMetrics;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledContainer = styled('div')({
|
||||||
|
marginLeft: 'auto',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledInfo = styled('div')(({ theme }) => ({
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledPercentage = styled('p')(({ theme }) => ({
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
textAlign: 'right',
|
||||||
|
fontSize: theme.fontSizes.bodySize,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledInfoParagraph = styled('p')(({ theme }) => ({
|
||||||
|
maxWidth: '270px',
|
||||||
|
marginTop: theme.spacing(0.5),
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
textAlign: 'right',
|
||||||
|
[theme.breakpoints.down(700)]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledIcon = styled(FiberManualRecord)(({ theme }) => ({
|
||||||
|
fill: theme.palette.standaloneBackground,
|
||||||
|
height: '75px',
|
||||||
|
width: '75px',
|
||||||
|
[theme.breakpoints.down(500)]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledPercentageCircle = styled('div')(({ theme }) => ({
|
||||||
|
margin: theme.spacing(0, 2),
|
||||||
|
[theme.breakpoints.down(500)]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const FeatureOverviewEnvironmentMetrics = ({
|
const FeatureOverviewEnvironmentMetrics = ({
|
||||||
environmentMetric,
|
environmentMetric,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}: IFeatureOverviewEnvironmentMetrics) => {
|
}: IFeatureOverviewEnvironmentMetrics) => {
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
if (!environmentMetric) return null;
|
if (!environmentMetric) return null;
|
||||||
@ -28,10 +71,9 @@ const FeatureOverviewEnvironmentMetrics = ({
|
|||||||
(environmentMetric.yes === 0 && environmentMetric.no === 0)
|
(environmentMetric.yes === 0 && environmentMetric.no === 0)
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<StyledContainer>
|
||||||
<div className={styles.info}>
|
<StyledInfo>
|
||||||
<p
|
<StyledPercentage
|
||||||
className={styles.percentage}
|
|
||||||
style={{
|
style={{
|
||||||
color: disabled
|
color: disabled
|
||||||
? theme.palette.text.secondary
|
? theme.palette.text.secondary
|
||||||
@ -40,9 +82,8 @@ const FeatureOverviewEnvironmentMetrics = ({
|
|||||||
data-loading
|
data-loading
|
||||||
>
|
>
|
||||||
{percentage}%
|
{percentage}%
|
||||||
</p>
|
</StyledPercentage>
|
||||||
<p
|
<StyledInfoParagraph
|
||||||
className={styles.infoParagraph}
|
|
||||||
style={{
|
style={{
|
||||||
color: disabled
|
color: disabled
|
||||||
? theme.palette.text.secondary
|
? theme.palette.text.secondary
|
||||||
@ -53,22 +94,18 @@ const FeatureOverviewEnvironmentMetrics = ({
|
|||||||
The feature has been requested <b>0 times</b> and
|
The feature has been requested <b>0 times</b> and
|
||||||
exposed
|
exposed
|
||||||
<b> 0 times</b> in the last hour
|
<b> 0 times</b> in the last hour
|
||||||
</p>
|
</StyledInfoParagraph>
|
||||||
</div>
|
</StyledInfo>
|
||||||
<FiberManualRecord
|
<StyledIcon style={{ transform: 'scale(1.1)' }} data-loading />
|
||||||
className={styles.icon}
|
</StyledContainer>
|
||||||
style={{ transform: 'scale(1.1)' }}
|
|
||||||
data-loading
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<StyledContainer>
|
||||||
<div className={styles.info}>
|
<StyledInfo>
|
||||||
<p className={styles.percentage}>{percentage}%</p>
|
<StyledPercentage>{percentage}%</StyledPercentage>
|
||||||
<p className={styles.infoParagraph}>
|
<StyledInfoParagraph>
|
||||||
The feature has been requested{' '}
|
The feature has been requested{' '}
|
||||||
<b>
|
<b>
|
||||||
<PrettifyLargeNumber value={total} /> times
|
<PrettifyLargeNumber value={total} /> times
|
||||||
@ -79,12 +116,12 @@ const FeatureOverviewEnvironmentMetrics = ({
|
|||||||
times
|
times
|
||||||
</b>{' '}
|
</b>{' '}
|
||||||
in the last hour
|
in the last hour
|
||||||
</p>
|
</StyledInfoParagraph>
|
||||||
</div>
|
</StyledInfo>
|
||||||
<div className={styles.percentageCircle} data-loading>
|
<StyledPercentageCircle data-loading>
|
||||||
<PercentageCircle percentage={percentage} size="3rem" />
|
<PercentageCircle percentage={percentage} size="3rem" />
|
||||||
</div>
|
</StyledPercentageCircle>
|
||||||
</div>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { capitalize } from '@mui/material';
|
import { capitalize, styled } from '@mui/material';
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { useStyles } from './FeatureOverviewMetadata.styles';
|
|
||||||
import { Edit } from '@mui/icons-material';
|
import { Edit } from '@mui/icons-material';
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
@ -13,9 +11,62 @@ import FeatureOverviewTags from './FeatureOverviewTags/FeatureOverviewTags';
|
|||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
|
||||||
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
color: theme.palette.text.tertiaryContrast,
|
||||||
|
backgroundColor: theme.palette.featureMetaData,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
maxWidth: '350px',
|
||||||
|
minWidth: '350px',
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
[theme.breakpoints.down(1000)]: {
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: 'none',
|
||||||
|
minWidth: 'auto',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledPaddingContainerTop = styled('div')({
|
||||||
|
padding: '1.5rem 1.5rem 0 1.5rem',
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledPaddingContainerBottom = styled('div')(({ theme }) => ({
|
||||||
|
padding: '0 1.5rem 1.5rem 1.5rem',
|
||||||
|
borderTop: `1px solid ${theme.palette.divider}`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledMetaDataHeader = styled('div')({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledHeader = styled('h2')(({ theme }) => ({
|
||||||
|
fontSize: theme.fontSizes.bodySize,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
margin: 0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledBody = styled('div')(({ theme }) => ({
|
||||||
|
margin: theme.spacing(2, 0),
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledBodyItem = styled('span')(({ theme }) => ({
|
||||||
|
margin: theme.spacing(1, 0),
|
||||||
|
fontSize: theme.fontSizes.bodySize,
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledDescriptionContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: theme.palette.text.tertiaryContrast,
|
||||||
|
}));
|
||||||
|
|
||||||
const FeatureOverviewMetaData = () => {
|
const FeatureOverviewMetaData = () => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const { tags } = useTags(featureId);
|
const { tags } = useTags(featureId);
|
||||||
@ -25,24 +76,29 @@ const FeatureOverviewMetaData = () => {
|
|||||||
const IconComponent = getFeatureTypeIcons(type);
|
const IconComponent = getFeatureTypeIcons(type);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(styles.container)}>
|
<StyledContainer>
|
||||||
<div className={styles.paddingContainerTop}>
|
<StyledPaddingContainerTop>
|
||||||
<div className={styles.metaDataHeader} data-loading>
|
<StyledMetaDataHeader data-loading>
|
||||||
<IconComponent className={styles.headerIcon} />{' '}
|
<IconComponent
|
||||||
<h2 className={styles.header}>
|
sx={theme => ({
|
||||||
{capitalize(type || '')} toggle
|
marginRight: theme.spacing(2),
|
||||||
</h2>
|
height: '40px',
|
||||||
</div>
|
width: '40px',
|
||||||
<div className={styles.body}>
|
fill: theme.palette.text.tertiaryContrast,
|
||||||
<span className={styles.bodyItem} data-loading>
|
})}
|
||||||
|
/>{' '}
|
||||||
|
<StyledHeader>{capitalize(type || '')} toggle</StyledHeader>
|
||||||
|
</StyledMetaDataHeader>
|
||||||
|
<StyledBody>
|
||||||
|
<StyledBodyItem data-loading>
|
||||||
Project: {project}
|
Project: {project}
|
||||||
</span>
|
</StyledBodyItem>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(description)}
|
condition={Boolean(description)}
|
||||||
show={
|
show={
|
||||||
<span className={styles.bodyItem} data-loading>
|
<StyledBodyItem data-loading>
|
||||||
<div>Description:</div>
|
<div>Description:</div>
|
||||||
<div className={styles.descriptionContainer}>
|
<StyledDescriptionContainer>
|
||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
<PermissionIconButton
|
<PermissionIconButton
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -53,14 +109,19 @@ const FeatureOverviewMetaData = () => {
|
|||||||
title: 'Edit description',
|
title: 'Edit description',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Edit className={styles.editIcon} />
|
<Edit
|
||||||
|
sx={theme => ({
|
||||||
|
color: theme.palette.text
|
||||||
|
.tertiaryContrast,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</PermissionIconButton>
|
</PermissionIconButton>
|
||||||
</div>
|
</StyledDescriptionContainer>
|
||||||
</span>
|
</StyledBodyItem>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<span data-loading>
|
<span data-loading>
|
||||||
<div className={styles.descriptionContainer}>
|
<StyledDescriptionContainer>
|
||||||
No description.{' '}
|
No description.{' '}
|
||||||
<PermissionIconButton
|
<PermissionIconButton
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -71,26 +132,31 @@ const FeatureOverviewMetaData = () => {
|
|||||||
title: 'Edit description',
|
title: 'Edit description',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Edit className={styles.editIcon} />
|
<Edit
|
||||||
|
sx={theme => ({
|
||||||
|
color: theme.palette.text
|
||||||
|
.tertiaryContrast,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</PermissionIconButton>
|
</PermissionIconButton>
|
||||||
</div>
|
</StyledDescriptionContainer>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledBody>
|
||||||
</div>
|
</StyledPaddingContainerTop>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={
|
condition={
|
||||||
tags.length > 0 &&
|
tags.length > 0 &&
|
||||||
!Boolean(uiConfig.flags.variantsPerEnvironment)
|
!Boolean(uiConfig.flags.variantsPerEnvironment)
|
||||||
}
|
}
|
||||||
show={
|
show={
|
||||||
<div className={styles.paddingContainerBottom}>
|
<StyledPaddingContainerBottom>
|
||||||
<FeatureOverviewTags projectId={projectId} />
|
<FeatureOverviewTags projectId={projectId} />
|
||||||
</div>
|
</StyledPaddingContainerBottom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
container: {
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
color: '#fff',
|
|
||||||
backgroundColor: theme.palette.featureMetaData,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
maxWidth: '350px',
|
|
||||||
minWidth: '350px',
|
|
||||||
marginRight: '1rem',
|
|
||||||
[theme.breakpoints.down(1000)]: {
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: 'none',
|
|
||||||
minWidth: 'auto',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
paddingContainerTop: {
|
|
||||||
padding: '1.5rem 1.5rem 0 1.5rem',
|
|
||||||
},
|
|
||||||
paddingContainerBottom: {
|
|
||||||
padding: '0 1.5rem 1.5rem 1.5rem',
|
|
||||||
borderTop: `1px solid ${theme.palette.grey[300]}`,
|
|
||||||
},
|
|
||||||
metaDataHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
fontSize: theme.fontSizes.bodySize,
|
|
||||||
fontWeight: 'normal',
|
|
||||||
margin: 0,
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
margin: '1rem 0',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
bodyItem: {
|
|
||||||
margin: '0.5rem 0',
|
|
||||||
fontSize: theme.fontSizes.bodySize,
|
|
||||||
wordBreak: 'break-all',
|
|
||||||
},
|
|
||||||
headerIcon: {
|
|
||||||
marginRight: '1rem',
|
|
||||||
height: '40px',
|
|
||||||
width: '40px',
|
|
||||||
fill: '#fff',
|
|
||||||
},
|
|
||||||
descriptionContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
editIcon: {
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,38 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
container: {
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
backgroundColor: theme.palette.primary.main,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
marginRight: '1rem',
|
|
||||||
marginTop: '1rem',
|
|
||||||
[theme.breakpoints.down(800)]: {
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tagHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
tag: {
|
|
||||||
height: '40px',
|
|
||||||
width: '40px',
|
|
||||||
fill: theme.palette.primary.main,
|
|
||||||
marginRight: '0.8rem',
|
|
||||||
},
|
|
||||||
tagChip: {
|
|
||||||
marginRight: '0.25rem',
|
|
||||||
marginTop: '0.5rem',
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
fontSize: theme.fontSizes.smallBody,
|
|
||||||
},
|
|
||||||
closeIcon: {
|
|
||||||
color: theme.palette.primary.light,
|
|
||||||
'&:hover': {
|
|
||||||
color: theme.palette.primary.light,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useContext, useState } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import { Chip } from '@mui/material';
|
import { Chip, styled } from '@mui/material';
|
||||||
import { Close, Label } from '@mui/icons-material';
|
import { Close, Label } from '@mui/icons-material';
|
||||||
import useTags from 'hooks/api/getters/useTags/useTags';
|
import useTags from 'hooks/api/getters/useTags/useTags';
|
||||||
import { useStyles } from './FeatureOverviewTags.styles';
|
|
||||||
import slackIcon from 'assets/icons/slack.svg';
|
import slackIcon from 'assets/icons/slack.svg';
|
||||||
import jiraIcon from 'assets/icons/jira.svg';
|
import jiraIcon from 'assets/icons/jira.svg';
|
||||||
import webhookIcon from 'assets/icons/webhooks.svg';
|
import webhookIcon from 'assets/icons/webhooks.svg';
|
||||||
@ -18,10 +17,37 @@ import AccessContext from 'contexts/AccessContext';
|
|||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
|
||||||
interface IFeatureOverviewTagsProps extends React.HTMLProps<HTMLDivElement> {
|
interface IFeatureOverviewTagsProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
[theme.breakpoints.down(800)]: {
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: 'none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledTagChip = styled(Chip)(({ theme }) => ({
|
||||||
|
marginRight: theme.spacing(0.5),
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
backgroundColor: theme.palette.text.tertiaryContrast,
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledCloseIcon = styled(Close)(({ theme }) => ({
|
||||||
|
color: theme.palette.primary.light,
|
||||||
|
'&:hover': {
|
||||||
|
color: theme.palette.primary.light,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
||||||
projectId,
|
projectId,
|
||||||
...rest
|
...rest
|
||||||
@ -31,7 +57,6 @@ const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
|||||||
value: '',
|
value: '',
|
||||||
type: '',
|
type: '',
|
||||||
});
|
});
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const { tags, refetch } = useTags(featureId);
|
const { tags, refetch } = useTags(featureId);
|
||||||
const { tagTypes } = useTagTypes();
|
const { tagTypes } = useTagTypes();
|
||||||
@ -98,15 +123,12 @@ const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderTag = (t: ITag) => (
|
const renderTag = (t: ITag) => (
|
||||||
<Chip
|
<StyledTagChip
|
||||||
icon={tagIcon(t.type)}
|
icon={tagIcon(t.type)}
|
||||||
className={styles.tagChip}
|
|
||||||
data-loading
|
data-loading
|
||||||
label={t.value}
|
label={t.value}
|
||||||
key={`${t.type}:${t.value}`}
|
key={`${t.type}:${t.value}`}
|
||||||
deleteIcon={
|
deleteIcon={<StyledCloseIcon titleAccess="Remove" />}
|
||||||
<Close className={styles.closeIcon} titleAccess="Remove" />
|
|
||||||
}
|
|
||||||
onDelete={
|
onDelete={
|
||||||
canDeleteTag
|
canDeleteTag
|
||||||
? () => {
|
? () => {
|
||||||
@ -119,7 +141,7 @@ const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container} {...rest}>
|
<StyledContainer {...rest}>
|
||||||
<Dialogue
|
<Dialogue
|
||||||
open={showDelDialog}
|
open={showDelDialog}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
@ -141,7 +163,7 @@ const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
|||||||
elseShow={<p data-loading>No tags to display</p>}
|
elseShow={<p data-loading>No tags to display</p>}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
innerContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
},
|
|
||||||
bodyContainer: {
|
|
||||||
padding: 0,
|
|
||||||
},
|
|
||||||
listContainer: {
|
|
||||||
width: '20%',
|
|
||||||
borderRight: `1px solid ${theme.palette.grey[300]}`,
|
|
||||||
padding: '1rem 0',
|
|
||||||
[theme.breakpoints.down('md')]: {
|
|
||||||
width: '35%',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
listItem: {
|
|
||||||
padding: '0.75rem 2rem',
|
|
||||||
},
|
|
||||||
innerBodyContainer: {
|
|
||||||
padding: '2rem',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: 400,
|
|
||||||
['& > *']: {
|
|
||||||
margin: '0.5rem 0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,7 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { useStyles } from './FeatureSettings.styles';
|
import { Box, List, ListItem, styled } from '@mui/material';
|
||||||
import { List, ListItem } from '@mui/material';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import FeatureSettingsProject from './FeatureSettingsProject/FeatureSettingsProject';
|
import FeatureSettingsProject from './FeatureSettingsProject/FeatureSettingsProject';
|
||||||
import { FeatureSettingsInformation } from './FeatureSettingsInformation/FeatureSettingsInformation';
|
import { FeatureSettingsInformation } from './FeatureSettingsInformation/FeatureSettingsInformation';
|
||||||
@ -11,21 +10,39 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
const METADATA = 'metadata';
|
const METADATA = 'metadata';
|
||||||
const PROJECT = 'project';
|
const PROJECT = 'project';
|
||||||
|
|
||||||
|
const StyledListContainer = styled('div')(({ theme }) => ({
|
||||||
|
width: '20%',
|
||||||
|
borderRight: `1px solid ${theme.palette.divider}`,
|
||||||
|
padding: theme.spacing(2, 0),
|
||||||
|
[theme.breakpoints.down('md')]: {
|
||||||
|
width: '35%',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledInnerBodyContainer = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(4),
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
width: 400,
|
||||||
|
['& > *']: {
|
||||||
|
margin: theme.spacing(1, 0),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
export const FeatureSettings = () => {
|
export const FeatureSettings = () => {
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const [settings, setSettings] = useState(METADATA);
|
const [settings, setSettings] = useState(METADATA);
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent header="Settings" bodyClass={styles.bodyContainer}>
|
<PageContent header="Settings" sx={{ padding: 0 }}>
|
||||||
<div className={styles.innerContainer}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<div className={styles.listContainer}>
|
<StyledListContainer>
|
||||||
<List>
|
<List>
|
||||||
<ListItem
|
<ListItem
|
||||||
key={0}
|
key={0}
|
||||||
className={styles.listItem}
|
sx={{ padding: '0.75rem 2rem' }}
|
||||||
button
|
button
|
||||||
onClick={() => setSettings(METADATA)}
|
onClick={() => setSettings(METADATA)}
|
||||||
selected={settings === METADATA}
|
selected={settings === METADATA}
|
||||||
@ -34,7 +51,7 @@ export const FeatureSettings = () => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
key={1}
|
key={1}
|
||||||
className={styles.listItem}
|
sx={{ padding: '0.75rem 2rem' }}
|
||||||
button
|
button
|
||||||
onClick={() => setSettings(PROJECT)}
|
onClick={() => setSettings(PROJECT)}
|
||||||
selected={settings === PROJECT}
|
selected={settings === PROJECT}
|
||||||
@ -43,8 +60,8 @@ export const FeatureSettings = () => {
|
|||||||
Project
|
Project
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</StyledListContainer>
|
||||||
<div className={styles.innerBodyContainer}>
|
<StyledInnerBodyContainer>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={settings === METADATA}
|
condition={settings === METADATA}
|
||||||
show={
|
show={
|
||||||
@ -58,8 +75,8 @@ export const FeatureSettings = () => {
|
|||||||
condition={settings === PROJECT && uiConfig.flags.P}
|
condition={settings === PROJECT && uiConfig.flags.P}
|
||||||
show={<FeatureSettingsProject />}
|
show={<FeatureSettingsProject />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</StyledInnerBodyContainer>
|
||||||
</div>
|
</Box>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user