mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-12 13:48:35 +02:00
feat: review your draft sidebar (#2305)
* refactor playground status chip component * fix: update change request sidebar * refactor: status badge cleanup * fix: prettier formatting
This commit is contained in:
parent
2f1f9cecc2
commit
0a855604af
@ -4,18 +4,18 @@ import { ChangeRequestFeatureToggleChange } from '../ChangeRequestOverview/Chang
|
|||||||
import { objectId } from 'utils/objectId';
|
import { objectId } from 'utils/objectId';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ToggleStatusChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ToggleStatusChange';
|
import { ToggleStatusChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ToggleStatusChange';
|
||||||
import type { IChangeRequestResponse } from 'hooks/api/getters/useChangeRequestDraft/useChangeRequestDraft';
|
|
||||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
|
import type { IChangeRequest } from '../changeRequest.types';
|
||||||
|
|
||||||
interface IChangeRequest {
|
interface IChangeRequestProps {
|
||||||
changeRequest: IChangeRequestResponse;
|
changeRequest: IChangeRequest;
|
||||||
onRefetch?: () => void;
|
onRefetch?: () => void;
|
||||||
onNavigate?: () => void;
|
onNavigate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChangeRequest: VFC<IChangeRequest> = ({
|
export const ChangeRequest: VFC<IChangeRequestProps> = ({
|
||||||
changeRequest,
|
changeRequest,
|
||||||
onRefetch,
|
onRefetch,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
@ -41,7 +41,6 @@ export const ChangeRequest: VFC<IChangeRequest> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
Changes
|
|
||||||
{changeRequest.features?.map(featureToggleChange => (
|
{changeRequest.features?.map(featureToggleChange => (
|
||||||
<ChangeRequestFeatureToggleChange
|
<ChangeRequestFeatureToggleChange
|
||||||
key={featureToggleChange.name}
|
key={featureToggleChange.name}
|
||||||
@ -55,6 +54,7 @@ export const ChangeRequest: VFC<IChangeRequest> = ({
|
|||||||
condition={change.action === 'updateEnabled'}
|
condition={change.action === 'updateEnabled'}
|
||||||
show={
|
show={
|
||||||
<ToggleStatusChange
|
<ToggleStatusChange
|
||||||
|
// @ts-expect-error TODO: fix types
|
||||||
enabled={change?.payload?.enabled}
|
enabled={change?.payload?.enabled}
|
||||||
onDiscard={onDiscard(change.id)}
|
onDiscard={onDiscard(change.id)}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { VFC } from 'react';
|
import { VFC } from 'react';
|
||||||
import { Link, Box, Typography } from '@mui/material';
|
import { Link, Box } from '@mui/material';
|
||||||
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
|
|
||||||
interface IPlaygroundResultsTable {
|
interface IPlaygroundResultsTable {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@ -16,11 +16,9 @@ export const ToggleStatusChange: VFC<IPlaygroundResultsTable> = ({
|
|||||||
<Box sx={{ p: 1, display: 'flex', justifyContent: 'space-between' }}>
|
<Box sx={{ p: 1, display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Box>
|
<Box>
|
||||||
New status:{' '}
|
New status:{' '}
|
||||||
<PlaygroundResultChip
|
<Badge color={enabled ? 'success' : 'error'}>
|
||||||
showIcon={false}
|
{enabled ? ' Enabled' : 'Disabled'}
|
||||||
label={enabled ? ' Enabled' : 'Disabled'}
|
</Badge>
|
||||||
enabled={enabled}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(onDiscard)}
|
condition={Boolean(onDiscard)}
|
||||||
|
@ -2,8 +2,8 @@ import { Box } from '@mui/material';
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Typography } from '@mui/material';
|
import { Typography } from '@mui/material';
|
||||||
import TimeAgo from 'react-timeago';
|
import TimeAgo from 'react-timeago';
|
||||||
import { resolveChangeRequestStatusIcon } from 'component/changeRequest/changeRequest.utils';
|
|
||||||
import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
|
import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
|
||||||
|
import { ChangeRequestStatusBadge } from 'component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge';
|
||||||
import {
|
import {
|
||||||
StyledPaper,
|
StyledPaper,
|
||||||
StyledContainer,
|
StyledContainer,
|
||||||
@ -22,7 +22,7 @@ export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
|||||||
<StyledHeader variant="h1">
|
<StyledHeader variant="h1">
|
||||||
Change request #{changeRequest.id}
|
Change request #{changeRequest.id}
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
{resolveChangeRequestStatusIcon(changeRequest.state)}
|
<ChangeRequestStatusBadge state={changeRequest.state} />;
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
<StyledInnerContainer>
|
<StyledInnerContainer>
|
||||||
<Typography variant="body2" sx={{ margin: 'auto 0' }}>
|
<Typography variant="body2" sx={{ margin: 'auto 0' }}>
|
||||||
|
@ -65,6 +65,7 @@ export const ChangeRequestOverview: FC = () => {
|
|||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
Changes
|
||||||
<ChangeRequest changeRequest={changeRequest} />
|
<ChangeRequest changeRequest={changeRequest} />
|
||||||
<ChangeRequestReviewStatus
|
<ChangeRequestReviewStatus
|
||||||
approved={
|
approved={
|
||||||
@ -72,7 +73,6 @@ export const ChangeRequestOverview: FC = () => {
|
|||||||
changeRequest.state === 'Applied'
|
changeRequest.state === 'Applied'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{ marginTop: 2 }}
|
sx={{ marginTop: 2 }}
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
import { VFC } from 'react';
|
import { VFC } from 'react';
|
||||||
import { Box, Button, Typography, styled, Tooltip } from '@mui/material';
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
styled,
|
||||||
|
Tooltip,
|
||||||
|
Divider,
|
||||||
|
} from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
|
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { HelpOutline } from '@mui/icons-material';
|
import { HelpOutline } from '@mui/icons-material';
|
||||||
|
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
||||||
import { ChangeRequest } from '../ChangeRequest/ChangeRequest';
|
import { ChangeRequest } from '../ChangeRequest/ChangeRequest';
|
||||||
import { useChangeRequestDraft } from 'hooks/api/getters/useChangeRequestDraft/useChangeRequestDraft';
|
import { useChangeRequestDraft } from 'hooks/api/getters/useChangeRequestDraft/useChangeRequestDraft';
|
||||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
|
import { ChangeRequestStatusBadge } from '../ChangeRequestStatusBadge/ChangeRequestStatusBadge';
|
||||||
|
|
||||||
interface IChangeRequestSidebarProps {
|
interface IChangeRequestSidebarProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
project: string;
|
project: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledPageContent = styled(PageContent)(({ theme }) => ({
|
const StyledPageContent = styled(PageContent)(({ theme }) => ({
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
@ -41,6 +51,11 @@ const StyledHeaderHint = styled('div')(({ theme }) => ({
|
|||||||
fontSize: theme.fontSizes.smallBody,
|
fontSize: theme.fontSizes.smallBody,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const BackButton = styled(Button)(({ theme }) => ({
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginLeft: 'auto',
|
||||||
|
}));
|
||||||
|
|
||||||
export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
||||||
open,
|
open,
|
||||||
project,
|
project,
|
||||||
@ -85,6 +100,7 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
>
|
>
|
||||||
There are no changes to review.
|
There are no changes to review.
|
||||||
{/* FIXME: empty state */}
|
{/* FIXME: empty state */}
|
||||||
|
<BackButton onClick={onClose}>Close</BackButton>
|
||||||
</StyledPageContent>
|
</StyledPageContent>
|
||||||
</SidebarModal>
|
</SidebarModal>
|
||||||
);
|
);
|
||||||
@ -126,13 +142,23 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
`${theme.shape.borderRadiusLarge}px`,
|
`${theme.shape.borderRadiusLarge}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography>
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
env: {environmentChangeRequest?.environment}
|
<Box sx={{ display: 'flex' }}>
|
||||||
|
<EnvironmentIcon enabled={true} />
|
||||||
|
<Typography component="span" variant="h2">
|
||||||
|
{environmentChangeRequest?.environment}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ ml: 'auto' }}>
|
||||||
|
<ChangeRequestStatusBadge
|
||||||
|
state={environmentChangeRequest?.state}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Divider sx={{ my: 3 }} />
|
||||||
|
<Typography variant="body1" color="text.secondary">
|
||||||
|
You request changes for these feature toggles:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
|
||||||
state: {environmentChangeRequest?.state}
|
|
||||||
</Typography>
|
|
||||||
<hr />
|
|
||||||
<ChangeRequest
|
<ChangeRequest
|
||||||
changeRequest={environmentChangeRequest}
|
changeRequest={environmentChangeRequest}
|
||||||
onNavigate={() => {
|
onNavigate={() => {
|
||||||
@ -144,20 +170,21 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={
|
condition={
|
||||||
environmentChangeRequest?.state ===
|
environmentChangeRequest?.state ===
|
||||||
'APPROVED'
|
'Approved'
|
||||||
}
|
|
||||||
show={<Typography>Applied</Typography>}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
environmentChangeRequest?.state === 'CLOSED'
|
|
||||||
}
|
}
|
||||||
show={<Typography>Applied</Typography>}
|
show={<Typography>Applied</Typography>}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={
|
condition={
|
||||||
environmentChangeRequest?.state ===
|
environmentChangeRequest?.state ===
|
||||||
'APPROVED'
|
'Applied'
|
||||||
|
}
|
||||||
|
show={<Typography>Applied</Typography>}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
environmentChangeRequest?.state ===
|
||||||
|
'Approved'
|
||||||
}
|
}
|
||||||
show={
|
show={
|
||||||
<>
|
<>
|
||||||
@ -201,6 +228,7 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
|
<BackButton onClick={onClose}>Close</BackButton>
|
||||||
</StyledPageContent>
|
</StyledPageContent>
|
||||||
</SidebarModal>
|
</SidebarModal>
|
||||||
);
|
);
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
import { ChangeRequestState } from './changeRequest.types';
|
import { VFC } from 'react';
|
||||||
|
import { ChangeRequestState } from '../changeRequest.types';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
import { Check, CircleOutlined, Close } from '@mui/icons-material';
|
import { Check, CircleOutlined, Close } from '@mui/icons-material';
|
||||||
|
|
||||||
export const resolveChangeRequestStatusIcon = (state: ChangeRequestState) => {
|
interface IChangeRequestStatusBadgeProps {
|
||||||
const reviewRequired = (
|
state: ChangeRequestState;
|
||||||
<Badge color="secondary" icon={<CircleOutlined fontSize={'small'} />}>
|
}
|
||||||
Review required
|
|
||||||
</Badge>
|
const ReviewRequiredBadge: VFC = () => (
|
||||||
);
|
<Badge color="secondary" icon={<CircleOutlined fontSize={'small'} />}>
|
||||||
|
Review required
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ChangeRequestStatusBadge: VFC<IChangeRequestStatusBadgeProps> = ({
|
||||||
|
state,
|
||||||
|
}) => {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'Draft':
|
case 'Draft':
|
||||||
return reviewRequired;
|
return <ReviewRequiredBadge />;
|
||||||
case 'In review':
|
case 'In review':
|
||||||
return reviewRequired;
|
return <ReviewRequiredBadge />;
|
||||||
case 'Approved':
|
case 'Approved':
|
||||||
return (
|
return (
|
||||||
<Badge color="success" icon={<Check fontSize={'small'} />}>
|
<Badge color="success" icon={<Check fontSize={'small'} />}>
|
||||||
@ -35,6 +43,6 @@ export const resolveChangeRequestStatusIcon = (state: ChangeRequestState) => {
|
|||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return reviewRequired;
|
return <ReviewRequiredBadge />;
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -1,10 +1,10 @@
|
|||||||
import { VFC } from 'react';
|
import { VFC } from 'react';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
import { resolveChangeRequestStatusIcon } from 'component/changeRequest/changeRequest.utils';
|
|
||||||
import { ChangeRequestState } from 'component/changeRequest/changeRequest.types';
|
import { ChangeRequestState } from 'component/changeRequest/changeRequest.types';
|
||||||
|
import { ChangeRequestStatusBadge } from 'component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge';
|
||||||
|
|
||||||
interface IChangeRequestStatusCellProps {
|
interface IChangeRequestStatusCellProps {
|
||||||
value?: string | null;
|
value?: string | null; // FIXME: proper type
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChangeRequestStatusCell: VFC<IChangeRequestStatusCellProps> = ({
|
export const ChangeRequestStatusCell: VFC<IChangeRequestStatusCellProps> = ({
|
||||||
@ -12,7 +12,7 @@ export const ChangeRequestStatusCell: VFC<IChangeRequestStatusCellProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const renderState = () => {
|
const renderState = () => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
return resolveChangeRequestStatusIcon(value as ChangeRequestState);
|
return <ChangeRequestStatusBadge state={value as ChangeRequestState} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { Chip } from '@mui/material';
|
import { Chip } from '@mui/material';
|
||||||
import { useStyles } from './StatusChip.styles';
|
import { useStyles } from './FeatureStatusChip.styles';
|
||||||
|
|
||||||
interface IStatusChip {
|
interface IStatusChip {
|
||||||
stale: boolean;
|
stale: boolean;
|
||||||
showActive?: boolean;
|
showActive?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatusChip = ({ stale, showActive = true }: IStatusChip) => {
|
export const FeatureStatusChip = ({
|
||||||
|
stale,
|
||||||
|
showActive = true,
|
||||||
|
}: IStatusChip) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
if (!stale && !showActive) {
|
if (!stale && !showActive) {
|
||||||
@ -30,5 +33,3 @@ const StatusChip = ({ stale, showActive = true }: IStatusChip) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StatusChip;
|
|
@ -1,208 +0,0 @@
|
|||||||
import { memo } from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Chip, ListItem, Tooltip } from '@mui/material';
|
|
||||||
import { Undo } from '@mui/icons-material';
|
|
||||||
import TimeAgo from 'react-timeago';
|
|
||||||
import { IAccessContext } from 'contexts/AccessContext';
|
|
||||||
import StatusChip from 'component/common/StatusChip/StatusChip';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { IFlags } from 'interfaces/uiConfig';
|
|
||||||
import { getTogglePath } from 'utils/routePathHelpers';
|
|
||||||
import FeatureStatus from 'component/feature/FeatureView/FeatureStatus/FeatureStatus';
|
|
||||||
import FeatureType from 'component/feature/FeatureView/FeatureType/FeatureType';
|
|
||||||
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
|
||||||
import { FeatureSchema } from 'openapi';
|
|
||||||
import { styles as themeStyles } from 'component/common';
|
|
||||||
import { useStyles } from './styles';
|
|
||||||
|
|
||||||
interface IFeatureToggleListItemProps {
|
|
||||||
feature: FeatureSchema;
|
|
||||||
onRevive?: (id: string) => void;
|
|
||||||
hasAccess: IAccessContext['hasAccess'];
|
|
||||||
flags?: IFlags;
|
|
||||||
inProject?: boolean;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const FeatureToggleListItem = memo<IFeatureToggleListItemProps>(
|
|
||||||
({
|
|
||||||
feature,
|
|
||||||
onRevive,
|
|
||||||
hasAccess,
|
|
||||||
flags = {},
|
|
||||||
inProject,
|
|
||||||
className,
|
|
||||||
...rest
|
|
||||||
}) => {
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
|
|
||||||
const { projects } = useProjects();
|
|
||||||
const isArchive = Boolean(onRevive);
|
|
||||||
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
stale,
|
|
||||||
createdAt,
|
|
||||||
project,
|
|
||||||
lastSeenAt,
|
|
||||||
} = feature;
|
|
||||||
|
|
||||||
const projectExists = () => {
|
|
||||||
let projectExist = projects.find(proj => proj.id === project);
|
|
||||||
if (projectExist) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const reviveFeature = () => {
|
|
||||||
if (projectExists() && onRevive) {
|
|
||||||
onRevive(feature.name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ListItem
|
|
||||||
{...rest}
|
|
||||||
className={classnames(styles.listItem, className)}
|
|
||||||
>
|
|
||||||
<span className={styles.listItemMetric}>
|
|
||||||
<FeatureStatus
|
|
||||||
lastSeenAt={lastSeenAt}
|
|
||||||
tooltipPlacement="left"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className={classnames(
|
|
||||||
styles.listItemType,
|
|
||||||
themeStyles.hideLt600
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<FeatureType type={type as string} />
|
|
||||||
</span>
|
|
||||||
<span className={classnames(styles.listItemLink)}>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={!isArchive}
|
|
||||||
show={
|
|
||||||
<Link
|
|
||||||
to={getTogglePath(feature.project!, name)}
|
|
||||||
className={classnames(
|
|
||||||
themeStyles.listLink,
|
|
||||||
themeStyles.truncate
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Tooltip title={description || ''} arrow>
|
|
||||||
<span className={themeStyles.toggleName}>
|
|
||||||
{name}
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
{/* <span className={styles.listItemToggle}></span> */}
|
|
||||||
<span></span>
|
|
||||||
<small>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(createdAt)}
|
|
||||||
show={() => (
|
|
||||||
<TimeAgo
|
|
||||||
date={createdAt as Date}
|
|
||||||
live={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</small>
|
|
||||||
<div>
|
|
||||||
<span className={themeStyles.truncate}>
|
|
||||||
<small>{description}</small>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<>
|
|
||||||
<Tooltip title={description || ''} arrow>
|
|
||||||
<span className={themeStyles.toggleName}>
|
|
||||||
{name} {' '}
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
{/* <span className={styles.listItemToggle}></span> */}
|
|
||||||
<span></span>
|
|
||||||
<small>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(createdAt)}
|
|
||||||
show={() => (
|
|
||||||
<TimeAgo
|
|
||||||
date={createdAt as Date}
|
|
||||||
live={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</small>
|
|
||||||
<div>
|
|
||||||
<span className={themeStyles.truncate}>
|
|
||||||
<small>{description}</small>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className={classnames(
|
|
||||||
styles.listItemStrategies,
|
|
||||||
themeStyles.hideLt920
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<StatusChip stale={Boolean(stale)} showActive={false} />
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={!inProject}
|
|
||||||
show={
|
|
||||||
<Link
|
|
||||||
to={`/projects/${project}`}
|
|
||||||
style={{ textDecoration: 'none' }}
|
|
||||||
className={classnames({
|
|
||||||
[`${styles.disabledLink}`]:
|
|
||||||
!projectExists(),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Chip
|
|
||||||
color="primary"
|
|
||||||
variant="outlined"
|
|
||||||
style={{
|
|
||||||
marginLeft: '8px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
title={`Project: ${project}`}
|
|
||||||
label={project}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={isArchive}
|
|
||||||
show={
|
|
||||||
<PermissionIconButton
|
|
||||||
permission={UPDATE_FEATURE}
|
|
||||||
projectId={project}
|
|
||||||
disabled={
|
|
||||||
!hasAccess(UPDATE_FEATURE, project) ||
|
|
||||||
!projectExists()
|
|
||||||
}
|
|
||||||
onClick={reviveFeature}
|
|
||||||
tooltipProps={{ title: 'Revive feature toggle' }}
|
|
||||||
>
|
|
||||||
<Undo />
|
|
||||||
</PermissionIconButton>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,291 +0,0 @@
|
|||||||
// Vitest Snapshot v1
|
|
||||||
|
|
||||||
exports[`renders correctly with one feature 1`] = `
|
|
||||||
[
|
|
||||||
<li
|
|
||||||
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
|
||||||
disabled={false}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemMetric-2"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-describedby={null}
|
|
||||||
className="makeStyles-container-8"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"background": "#EDF0F1",
|
|
||||||
"fontSize": "0.8rem",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="No usage reported from connected applications"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"fontSize": "1.4rem",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
⊕
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemType-3 _hideLt600_1yorl_42"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-describedby={null}
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root makeStyles-icon-9"
|
|
||||||
data-loading={true}
|
|
||||||
focusable="false"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="This is a \\"\\" toggle"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemLink-5"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="_listLink_1yorl_25 _truncate_1yorl_2"
|
|
||||||
href="/projects/default/features/Another"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-describedby={null}
|
|
||||||
className="_toggleName_1yorl_84"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="another's description"
|
|
||||||
>
|
|
||||||
Another
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span />
|
|
||||||
<small>
|
|
||||||
<time
|
|
||||||
dateTime="2018-02-04T20:27:52.127Z"
|
|
||||||
title="2018-02-04T20:27:52.127Z"
|
|
||||||
>
|
|
||||||
4 years ago
|
|
||||||
</time>
|
|
||||||
</small>
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
className="_truncate_1yorl_2"
|
|
||||||
>
|
|
||||||
<small>
|
|
||||||
another's description
|
|
||||||
</small>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemStrategies-6 _hideLt920_1yorl_37"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="makeStyles-disabledLink-7"
|
|
||||||
href="/projects/default"
|
|
||||||
onClick={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"textDecoration": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"cursor": "pointer",
|
|
||||||
"marginLeft": "8px",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="Project: default"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiChip-label"
|
|
||||||
>
|
|
||||||
default
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</li>,
|
|
||||||
<div
|
|
||||||
aria-atomic={true}
|
|
||||||
aria-live="polite"
|
|
||||||
className="makeStyles-container-11"
|
|
||||||
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
|
||||||
role="status"
|
|
||||||
/>,
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`renders correctly with one feature without permission 1`] = `
|
|
||||||
[
|
|
||||||
<li
|
|
||||||
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
|
||||||
disabled={false}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemMetric-2"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-describedby={null}
|
|
||||||
className="makeStyles-container-8"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"background": "#EDF0F1",
|
|
||||||
"fontSize": "0.8rem",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="No usage reported from connected applications"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"fontSize": "1.4rem",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
⊕
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemType-3 _hideLt600_1yorl_42"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-describedby={null}
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root makeStyles-icon-9"
|
|
||||||
data-loading={true}
|
|
||||||
focusable="false"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="This is a \\"\\" toggle"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemLink-5"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="_listLink_1yorl_25 _truncate_1yorl_2"
|
|
||||||
href="/projects/undefined/features/Another"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-describedby={null}
|
|
||||||
className="_toggleName_1yorl_84"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="another's description"
|
|
||||||
>
|
|
||||||
Another
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span />
|
|
||||||
<small>
|
|
||||||
<time
|
|
||||||
dateTime="2018-02-04T20:27:52.127Z"
|
|
||||||
title="2018-02-04T20:27:52.127Z"
|
|
||||||
>
|
|
||||||
4 years ago
|
|
||||||
</time>
|
|
||||||
</small>
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
className="_truncate_1yorl_2"
|
|
||||||
>
|
|
||||||
<small>
|
|
||||||
another's description
|
|
||||||
</small>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="makeStyles-listItemStrategies-6 _hideLt920_1yorl_37"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="makeStyles-disabledLink-7"
|
|
||||||
href="/projects/undefined"
|
|
||||||
onClick={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"textDecoration": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"cursor": "pointer",
|
|
||||||
"marginLeft": "8px",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="Project: undefined"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiChip-label"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</li>,
|
|
||||||
<div
|
|
||||||
aria-atomic={true}
|
|
||||||
aria-live="polite"
|
|
||||||
className="makeStyles-container-11"
|
|
||||||
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
|
||||||
role="status"
|
|
||||||
/>,
|
|
||||||
]
|
|
||||||
`;
|
|
@ -1,37 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
listItem: {
|
|
||||||
padding: '0',
|
|
||||||
margin: '1rem 0',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: theme.palette.grey[200],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
listItemMetric: {
|
|
||||||
width: '40px',
|
|
||||||
marginRight: '0.25rem',
|
|
||||||
flexShrink: 0,
|
|
||||||
},
|
|
||||||
listItemType: {
|
|
||||||
width: '40px',
|
|
||||||
textAlign: 'center',
|
|
||||||
marginRight: '0',
|
|
||||||
flexShrink: 0,
|
|
||||||
},
|
|
||||||
listItemSvg: {
|
|
||||||
fill: theme.palette.grey[300],
|
|
||||||
},
|
|
||||||
listItemLink: {
|
|
||||||
marginLeft: '0.25rem',
|
|
||||||
minWidth: '0',
|
|
||||||
},
|
|
||||||
listItemStrategies: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
disabledLink: {
|
|
||||||
pointerEvents: 'none',
|
|
||||||
},
|
|
||||||
}));
|
|
@ -86,7 +86,7 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
const toggleEnvironment = async (e: React.ChangeEvent) => {
|
const toggleEnvironment = async (e: React.ChangeEvent) => {
|
||||||
if (uiConfig?.flags?.changeRequests && env.name === 'production') {
|
if (uiConfig?.flags?.changeRequests && env.name === 'production') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onChangeRequestToggle(featureId, env.name, env.enabled);
|
onChangeRequestToggle(featureId, env.name, !env.enabled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (env.enabled) {
|
if (env.enabled) {
|
||||||
|
@ -26,7 +26,7 @@ import useLoading from 'hooks/useLoading';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { FeatureStaleDialog } from 'component/common/FeatureStaleDialog/FeatureStaleDialog';
|
import { FeatureStaleDialog } from 'component/common/FeatureStaleDialog/FeatureStaleDialog';
|
||||||
import AddTagDialog from './FeatureOverview/AddTagDialog/AddTagDialog';
|
import AddTagDialog from './FeatureOverview/AddTagDialog/AddTagDialog';
|
||||||
import StatusChip from 'component/common/StatusChip/StatusChip';
|
import { FeatureStatusChip } from 'component/common/FeatureStatusChip/FeatureStatusChip';
|
||||||
import { FeatureNotFound } from 'component/feature/FeatureView/FeatureNotFound/FeatureNotFound';
|
import { FeatureNotFound } from 'component/feature/FeatureView/FeatureNotFound/FeatureNotFound';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { FeatureArchiveDialog } from '../../common/FeatureArchiveDialog/FeatureArchiveDialog';
|
import { FeatureArchiveDialog } from '../../common/FeatureArchiveDialog/FeatureArchiveDialog';
|
||||||
@ -111,7 +111,7 @@ export const FeatureView = () => {
|
|||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={!smallScreen}
|
condition={!smallScreen}
|
||||||
show={
|
show={
|
||||||
<StatusChip
|
<FeatureStatusChip
|
||||||
stale={feature?.stale}
|
stale={feature?.stale}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { VFC } from 'react';
|
import { VFC } from 'react';
|
||||||
import { Chip, styled, useTheme } from '@mui/material';
|
import { useTheme } from '@mui/material';
|
||||||
import { colors } from 'themes/colors';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ReactComponent as FeatureEnabledIcon } from 'assets/icons/isenabled-true.svg';
|
import { ReactComponent as FeatureEnabledIcon } from 'assets/icons/isenabled-true.svg';
|
||||||
import { ReactComponent as FeatureDisabledIcon } from 'assets/icons/isenabled-false.svg';
|
import { ReactComponent as FeatureDisabledIcon } from 'assets/icons/isenabled-false.svg';
|
||||||
import { WarningOutlined } from '@mui/icons-material';
|
import { WarningOutlined } from '@mui/icons-material';
|
||||||
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
|
|
||||||
interface IResultChipProps {
|
interface IResultChipProps {
|
||||||
enabled: boolean | 'unevaluated' | 'unknown';
|
enabled: boolean | 'unevaluated' | 'unknown';
|
||||||
@ -13,51 +13,6 @@ interface IResultChipProps {
|
|||||||
showIcon?: boolean;
|
showIcon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StyledChip = styled(Chip)(({ theme, icon }) => ({
|
|
||||||
padding: theme.spacing(0, 1),
|
|
||||||
height: 24,
|
|
||||||
borderRadius: theme.shape.borderRadius,
|
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
|
||||||
['& .MuiChip-label']: {
|
|
||||||
padding: 0,
|
|
||||||
paddingLeft: Boolean(icon) ? theme.spacing(0.5) : 0,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledFalseChip = styled(StyledChip)(({ theme }) => ({
|
|
||||||
border: `1px solid ${theme.palette.error.main}`,
|
|
||||||
backgroundColor: colors.red['200'],
|
|
||||||
['& .MuiChip-label']: {
|
|
||||||
color: theme.palette.error.main,
|
|
||||||
},
|
|
||||||
['& .MuiChip-icon']: {
|
|
||||||
color: theme.palette.error.main,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledTrueChip = styled(StyledChip)(({ theme }) => ({
|
|
||||||
border: `1px solid ${theme.palette.success.main}`,
|
|
||||||
backgroundColor: colors.green['100'],
|
|
||||||
['& .MuiChip-label']: {
|
|
||||||
color: theme.palette.success.main,
|
|
||||||
},
|
|
||||||
['& .MuiChip-icon']: {
|
|
||||||
color: theme.palette.success.main,
|
|
||||||
marginRight: 0,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledUnknownChip = styled(StyledChip)(({ theme }) => ({
|
|
||||||
border: `1px solid ${theme.palette.warning.main}`,
|
|
||||||
backgroundColor: colors.orange['100'],
|
|
||||||
['& .MuiChip-label']: {
|
|
||||||
color: theme.palette.warning.main,
|
|
||||||
},
|
|
||||||
['& .MuiChip-icon']: {
|
|
||||||
color: theme.palette.warning.main,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
||||||
enabled,
|
enabled,
|
||||||
label,
|
label,
|
||||||
@ -92,25 +47,25 @@ export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
|||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={enabled === 'unknown' || enabled === 'unevaluated'}
|
condition={enabled === 'unknown' || enabled === 'unevaluated'}
|
||||||
show={
|
show={
|
||||||
<StyledUnknownChip
|
<Badge icon={showIcon ? icon : undefined} color="warning">
|
||||||
icon={showIcon ? icon : undefined}
|
{label}
|
||||||
label={label}
|
</Badge>
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={typeof enabled === 'boolean' && Boolean(enabled)}
|
condition={typeof enabled === 'boolean' && Boolean(enabled)}
|
||||||
show={
|
show={
|
||||||
<StyledTrueChip
|
<Badge
|
||||||
|
color="success"
|
||||||
icon={showIcon ? icon : undefined}
|
icon={showIcon ? icon : undefined}
|
||||||
label={label}
|
>
|
||||||
/>
|
{label}
|
||||||
|
</Badge>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<StyledFalseChip
|
<Badge color="error" icon={showIcon ? icon : undefined}>
|
||||||
icon={showIcon ? icon : undefined}
|
{label}
|
||||||
label={label}
|
</Badge>
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -2,37 +2,10 @@ import useSWR from 'swr';
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { formatApiPath } from 'utils/formatPath';
|
import { formatApiPath } from 'utils/formatPath';
|
||||||
import handleErrorResponses from '../httpErrorResponseHandler';
|
import handleErrorResponses from '../httpErrorResponseHandler';
|
||||||
|
import {
|
||||||
interface IChange {
|
ChangeRequestState,
|
||||||
id: number;
|
IChangeRequest,
|
||||||
action: string;
|
} from 'component/changeRequest/changeRequest.types';
|
||||||
payload: {
|
|
||||||
enabled: boolean; // FIXME: add other action types
|
|
||||||
};
|
|
||||||
createdAt: Date;
|
|
||||||
createdBy: {
|
|
||||||
id: number;
|
|
||||||
username?: any;
|
|
||||||
imageUrl?: any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IChangeRequestResponse {
|
|
||||||
id: number;
|
|
||||||
environment: string;
|
|
||||||
state: string;
|
|
||||||
project: string;
|
|
||||||
createdBy: {
|
|
||||||
id: number;
|
|
||||||
username?: any;
|
|
||||||
imageUrl?: any;
|
|
||||||
};
|
|
||||||
createdAt: Date;
|
|
||||||
features: Array<{
|
|
||||||
name: string;
|
|
||||||
changes: IChange[];
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetcher = (path: string) => {
|
const fetcher = (path: string) => {
|
||||||
return fetch(path)
|
return fetch(path)
|
||||||
@ -41,7 +14,7 @@ const fetcher = (path: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useChangeRequestDraft = (project: string) => {
|
export const useChangeRequestDraft = (project: string) => {
|
||||||
const { data, error, mutate } = useSWR<IChangeRequestResponse[]>(
|
const { data, error, mutate } = useSWR<IChangeRequest[]>(
|
||||||
formatApiPath(`api/admin/projects/${project}/change-requests/draft`),
|
formatApiPath(`api/admin/projects/${project}/change-requests/draft`),
|
||||||
fetcher
|
fetcher
|
||||||
);
|
);
|
||||||
|
@ -28,6 +28,10 @@ export default createTheme({
|
|||||||
fontSize: '1.5rem',
|
fontSize: '1.5rem',
|
||||||
lineHeight: 1.875,
|
lineHeight: 1.875,
|
||||||
},
|
},
|
||||||
|
h2: {
|
||||||
|
fontSize: `${20 / 16}rem`,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
h3: {
|
h3: {
|
||||||
fontSize: '1rem',
|
fontSize: '1rem',
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
|
Loading…
Reference in New Issue
Block a user