mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-31 00:16:47 +01:00
feat: add UI to variant metrics (#3697)
This commit is contained in:
parent
6053963750
commit
bacb73667a
@ -7,7 +7,6 @@ import { Badge } from 'component/common/Badge/Badge';
|
||||
import { GroupCardActions } from './GroupCardActions/GroupCardActions';
|
||||
import TopicOutlinedIcon from '@mui/icons-material/TopicOutlined';
|
||||
import { IProjectRole } from 'interfaces/role';
|
||||
import { IProject } from 'interfaces/project';
|
||||
|
||||
const StyledLink = styled(Link)(({ theme }) => ({
|
||||
textDecoration: 'none',
|
||||
|
@ -34,7 +34,6 @@ import { ArchivedFeatureDeleteConfirm } from './ArchivedFeatureActionCell/Archiv
|
||||
import { IFeatureToggle } from 'interfaces/featureToggle';
|
||||
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
||||
import { RowSelectCell } from '../../project/Project/ProjectFeatureToggles/RowSelectCell/RowSelectCell';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { BatchSelectionActionsBar } from '../../common/BatchSelectionActionsBar/BatchSelectionActionsBar';
|
||||
import { ArchiveBatchActions } from './ArchiveBatchActions';
|
||||
|
||||
@ -64,7 +63,6 @@ export const ArchiveTable = ({
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||
const [deletedFeature, setDeletedFeature] = useState<IFeatureToggle>();
|
||||
|
@ -5,7 +5,6 @@ import Input from 'component/common/Input/Input';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import useToast from 'hooks/useToast';
|
||||
import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
interface IArchivedFeatureDeleteConfirmProps {
|
||||
deletedFeatures: string[];
|
||||
@ -35,8 +34,7 @@ export const ArchivedFeatureDeleteConfirm = ({
|
||||
}: IArchivedFeatureDeleteConfirmProps) => {
|
||||
const [confirmName, setConfirmName] = useState('');
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { deleteFeature, deleteFeatures } = useProjectApi();
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { deleteFeatures } = useProjectApi();
|
||||
|
||||
const onDeleteFeatureToggle = async () => {
|
||||
try {
|
||||
|
@ -13,9 +13,7 @@ import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
|
||||
import { changesCount } from '../../../changesCount';
|
||||
import {
|
||||
Box,
|
||||
IconButton,
|
||||
Link,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
@ -25,7 +23,7 @@ import {
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Delete, Edit, GroupRounded, MoreVert } from '@mui/icons-material';
|
||||
import { Delete, Edit, MoreVert } from '@mui/icons-material';
|
||||
import { EditChange } from './EditChange';
|
||||
|
||||
const useShowActions = (changeRequest: IChangeRequest, change: IChange) => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||
import { Link, styled, Typography } from '@mui/material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { useTheme } from '@mui/system';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
|
||||
interface IChangeRequestTitleCellProps {
|
||||
|
@ -4,9 +4,10 @@ import { ILocationSettings } from 'hooks/useLocationSettings';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { Theme } from '@mui/material/styles/createTheme';
|
||||
|
||||
interface IPoint {
|
||||
export interface IPoint {
|
||||
x: string;
|
||||
y: number;
|
||||
variants: Record<string, number>;
|
||||
}
|
||||
|
||||
export const createChartData = (
|
||||
@ -15,7 +16,7 @@ export const createChartData = (
|
||||
locationSettings: ILocationSettings
|
||||
): ChartData<'line', IPoint[], string> => {
|
||||
const requestsSeries = {
|
||||
label: 'total requests',
|
||||
label: 'Total requests',
|
||||
borderColor: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
data: createChartPoints(metrics, locationSettings, m => m.yes + m.no),
|
||||
@ -31,7 +32,7 @@ export const createChartData = (
|
||||
};
|
||||
|
||||
const yesSeries = {
|
||||
label: 'exposed',
|
||||
label: 'Exposed',
|
||||
borderColor: theme.palette.success.main,
|
||||
backgroundColor: theme.palette.success.main,
|
||||
data: createChartPoints(metrics, locationSettings, m => m.yes),
|
||||
@ -44,7 +45,7 @@ export const createChartData = (
|
||||
};
|
||||
|
||||
const noSeries = {
|
||||
label: 'not exposed',
|
||||
label: 'Not exposed',
|
||||
borderColor: theme.palette.error.main,
|
||||
backgroundColor: theme.palette.error.main,
|
||||
data: createChartPoints(metrics, locationSettings, m => m.no),
|
||||
@ -57,7 +58,9 @@ export const createChartData = (
|
||||
},
|
||||
};
|
||||
|
||||
return { datasets: [yesSeries, noSeries, requestsSeries] };
|
||||
return {
|
||||
datasets: [yesSeries, noSeries, requestsSeries],
|
||||
};
|
||||
};
|
||||
|
||||
const createChartPoints = (
|
||||
@ -68,5 +71,6 @@ const createChartPoints = (
|
||||
return metrics.map(metric => ({
|
||||
x: metric.timestamp,
|
||||
y: y(metric),
|
||||
variants: metric.variants,
|
||||
}));
|
||||
};
|
||||
|
@ -4,6 +4,17 @@ import { ChartOptions, defaults } from 'chart.js';
|
||||
import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
|
||||
import { formatDateHM } from 'utils/formatDate';
|
||||
import { Theme } from '@mui/material/styles/createTheme';
|
||||
import { IPoint } from './createChartData';
|
||||
|
||||
const formatVariantEntry = (
|
||||
variant: [string, number],
|
||||
totalExposure: number
|
||||
) => {
|
||||
if (totalExposure === 0) return '';
|
||||
const [key, value] = variant;
|
||||
const percentage = Math.floor((Number(value) / totalExposure) * 100);
|
||||
return `${value} (${percentage}%) - ${key}`;
|
||||
};
|
||||
|
||||
export const createChartOptions = (
|
||||
theme: Theme,
|
||||
@ -30,15 +41,38 @@ export const createChartOptions = (
|
||||
padding: 10,
|
||||
boxPadding: 5,
|
||||
usePointStyle: true,
|
||||
itemSort: (a, b) => {
|
||||
const order = ['Total requests', 'Exposed', 'Not exposed'];
|
||||
const aIndex = order.indexOf(a.dataset.label!);
|
||||
const bIndex = order.indexOf(b.dataset.label!);
|
||||
return aIndex - bIndex;
|
||||
},
|
||||
callbacks: {
|
||||
label: item => {
|
||||
return `${item.formattedValue} - ${item.dataset.label}`;
|
||||
},
|
||||
afterLabel: item => {
|
||||
const data = item.dataset.data[
|
||||
item.dataIndex
|
||||
] as unknown as IPoint;
|
||||
|
||||
if (
|
||||
item.dataset.label !== 'Exposed' ||
|
||||
data.variants === undefined
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
const { disabled, ...actualVariants } = data.variants;
|
||||
return Object.entries(actualVariants)
|
||||
.map(entry => formatVariantEntry(entry, data.y))
|
||||
.join('\n');
|
||||
},
|
||||
title: items =>
|
||||
formatDateHM(
|
||||
`Time: ${formatDateHM(
|
||||
items[0].parsed.x,
|
||||
locationSettings.locale
|
||||
),
|
||||
)}`,
|
||||
},
|
||||
// Sort tooltip items in the same order as the lines in the chart.
|
||||
itemSort: (a, b) => b.parsed.y - a.parsed.y,
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
@ -88,4 +88,5 @@ export interface IFeatureMetricsRaw {
|
||||
timestamp: string;
|
||||
yes: number;
|
||||
no: number;
|
||||
variants: Record<string, number>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user