mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
Fix: insights loading (#6834)
Loading state for - charts (placeholder data, animation) - user stats - loading skeleton animation - empty flags stats - kept other "stat" widgets as-is, usually not visible
This commit is contained in:
parent
1f4febbd3c
commit
e10ad7257f
@ -1,4 +1,6 @@
|
|||||||
import { ConditionallyRender } from '../common/ConditionallyRender/ConditionallyRender';
|
import type { VFC } from 'react';
|
||||||
|
import { Box, styled } from '@mui/material';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { Widget } from './components/Widget/Widget';
|
import { Widget } from './components/Widget/Widget';
|
||||||
import { UserStats } from './componentsStat/UserStats/UserStats';
|
import { UserStats } from './componentsStat/UserStats/UserStats';
|
||||||
import { UsersChart } from './componentsChart/UsersChart/UsersChart';
|
import { UsersChart } from './componentsChart/UsersChart/UsersChart';
|
||||||
@ -18,9 +20,7 @@ import type {
|
|||||||
InstanceInsightsSchemaUsers,
|
InstanceInsightsSchemaUsers,
|
||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import type { GroupedDataByProject } from './hooks/useGroupedProjectTrends';
|
import type { GroupedDataByProject } from './hooks/useGroupedProjectTrends';
|
||||||
import { Box, styled } from '@mui/material';
|
import { allOption } from 'component/common/ProjectSelect/ProjectSelect';
|
||||||
import { allOption } from '../common/ProjectSelect/ProjectSelect';
|
|
||||||
import type { VFC } from 'react';
|
|
||||||
import { chartInfo } from './chart-info';
|
import { chartInfo } from './chart-info';
|
||||||
|
|
||||||
interface IChartsProps {
|
interface IChartsProps {
|
||||||
@ -107,6 +107,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
count={users.total}
|
count={users.total}
|
||||||
active={users.active}
|
active={users.active}
|
||||||
inactive={users.inactive}
|
inactive={users.inactive}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
}
|
}
|
||||||
@ -116,7 +117,10 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
? chartInfo.usersInProject
|
? chartInfo.usersInProject
|
||||||
: chartInfo.avgUsersPerProject)}
|
: chartInfo.avgUsersPerProject)}
|
||||||
>
|
>
|
||||||
<UserStats count={summary.averageUsers} />
|
<UserStats
|
||||||
|
count={summary.averageUsers}
|
||||||
|
isLoading={loading}
|
||||||
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -134,6 +138,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
<ChartWidget {...chartInfo.usersPerProject}>
|
<ChartWidget {...chartInfo.usersPerProject}>
|
||||||
<UsersPerProjectChart
|
<UsersPerProjectChart
|
||||||
projectFlagTrends={groupedProjectsData}
|
projectFlagTrends={groupedProjectsData}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</ChartWidget>
|
</ChartWidget>
|
||||||
}
|
}
|
||||||
@ -144,6 +149,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
flagsPerUser={
|
flagsPerUser={
|
||||||
showAllProjects ? getFlagsPerUser(flags, users) : ''
|
showAllProjects ? getFlagsPerUser(flags, users) : ''
|
||||||
}
|
}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -160,6 +166,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
<ChartWidget {...chartInfo.flagsPerProject}>
|
<ChartWidget {...chartInfo.flagsPerProject}>
|
||||||
<FlagsProjectChart
|
<FlagsProjectChart
|
||||||
projectFlagTrends={groupedProjectsData}
|
projectFlagTrends={groupedProjectsData}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</ChartWidget>
|
</ChartWidget>
|
||||||
}
|
}
|
||||||
@ -180,6 +187,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
<ProjectHealthChart
|
<ProjectHealthChart
|
||||||
projectFlagTrends={groupedProjectsData}
|
projectFlagTrends={groupedProjectsData}
|
||||||
isAggregate={showAllProjects}
|
isAggregate={showAllProjects}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</ChartWidget>
|
</ChartWidget>
|
||||||
<Widget {...chartInfo.medianTimeToProduction}>
|
<Widget {...chartInfo.medianTimeToProduction}>
|
||||||
@ -195,6 +203,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
<TimeToProductionChart
|
<TimeToProductionChart
|
||||||
projectFlagTrends={groupedProjectsData}
|
projectFlagTrends={groupedProjectsData}
|
||||||
isAggregate={showAllProjects}
|
isAggregate={showAllProjects}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</ChartWidget>
|
</ChartWidget>
|
||||||
</StyledGrid>
|
</StyledGrid>
|
||||||
@ -207,6 +216,7 @@ export const InsightsCharts: VFC<IChartsProps> = ({
|
|||||||
metricsSummaryTrends={groupedMetricsData}
|
metricsSummaryTrends={groupedMetricsData}
|
||||||
allDatapointsSorted={allMetricsDatapoints}
|
allDatapointsSorted={allMetricsDatapoints}
|
||||||
isAggregate={showAllProjects}
|
isAggregate={showAllProjects}
|
||||||
|
isLoading={loading}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget
|
<Widget
|
||||||
|
@ -116,6 +116,7 @@ const LineChartComponent: VFC<{
|
|||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<Line
|
<Line
|
||||||
|
key={cover ? 'cover' : 'chart'}
|
||||||
options={options}
|
options={options}
|
||||||
data={data}
|
data={data}
|
||||||
plugins={[customHighlightPlugin]}
|
plugins={[customHighlightPlugin]}
|
||||||
|
@ -18,7 +18,7 @@ export const FlagsChart: VFC<IFlagsChartProps> = ({
|
|||||||
isLoading,
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const notEnoughData = flagTrends.length < 2;
|
const notEnoughData = !isLoading && flagTrends.length < 2;
|
||||||
const placeholderData = usePlaceholderData({ fill: true, type: 'double' });
|
const placeholderData = usePlaceholderData({ fill: true, type: 'double' });
|
||||||
|
|
||||||
const data = useMemo(
|
const data = useMemo(
|
||||||
|
@ -13,10 +13,12 @@ interface IFlagsProjectChartProps {
|
|||||||
projectFlagTrends: GroupedDataByProject<
|
projectFlagTrends: GroupedDataByProject<
|
||||||
InstanceInsightsSchema['projectFlagTrends']
|
InstanceInsightsSchema['projectFlagTrends']
|
||||||
>;
|
>;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const placeholderData = usePlaceholderData({
|
const placeholderData = usePlaceholderData({
|
||||||
type: 'constant',
|
type: 'constant',
|
||||||
@ -24,20 +26,22 @@ export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
|||||||
|
|
||||||
const data = useProjectChartData(projectFlagTrends);
|
const data = useProjectChartData(projectFlagTrends);
|
||||||
const notEnoughData = useMemo(
|
const notEnoughData = useMemo(
|
||||||
() => (data.datasets.some((d) => d.data.length > 1) ? false : true),
|
() =>
|
||||||
[data],
|
!isLoading &&
|
||||||
|
(data.datasets.some((d) => d.data.length > 1) ? false : true),
|
||||||
|
[data, isLoading],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LineChart
|
<LineChart
|
||||||
data={notEnoughData ? placeholderData : data}
|
data={notEnoughData || isLoading ? placeholderData : data}
|
||||||
overrideOptions={{
|
overrideOptions={{
|
||||||
parsing: {
|
parsing: {
|
||||||
yAxisKey: 'total',
|
yAxisKey: 'total',
|
||||||
xAxisKey: 'date',
|
xAxisKey: 'date',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
cover={notEnoughData ? <NotEnoughData /> : false}
|
cover={notEnoughData ? <NotEnoughData /> : isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,12 +20,14 @@ interface IMetricsSummaryChartProps {
|
|||||||
>;
|
>;
|
||||||
isAggregate?: boolean;
|
isAggregate?: boolean;
|
||||||
allDatapointsSorted: string[];
|
allDatapointsSorted: string[];
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
||||||
metricsSummaryTrends,
|
metricsSummaryTrends,
|
||||||
isAggregate,
|
isAggregate,
|
||||||
allDatapointsSorted,
|
allDatapointsSorted,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const metricsSummary = useFilledMetricsSummary(
|
const metricsSummary = useFilledMetricsSummary(
|
||||||
@ -33,8 +35,10 @@ export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
|||||||
allDatapointsSorted,
|
allDatapointsSorted,
|
||||||
);
|
);
|
||||||
const notEnoughData = useMemo(
|
const notEnoughData = useMemo(
|
||||||
() => !metricsSummary.datasets.some((d) => d.data.length > 1),
|
() =>
|
||||||
[metricsSummary],
|
!isLoading &&
|
||||||
|
!metricsSummary.datasets.some((d) => d.data.length > 1),
|
||||||
|
[metricsSummary, isLoading],
|
||||||
);
|
);
|
||||||
const placeholderData = usePlaceholderData();
|
const placeholderData = usePlaceholderData();
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<LineChart
|
<LineChart
|
||||||
data={notEnoughData ? placeholderData : data}
|
data={notEnoughData || isLoading ? placeholderData : data}
|
||||||
TooltipComponent={MetricsSummaryTooltip}
|
TooltipComponent={MetricsSummaryTooltip}
|
||||||
overrideOptions={
|
overrideOptions={
|
||||||
notEnoughData
|
notEnoughData
|
||||||
@ -79,7 +83,7 @@ export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cover={notEnoughData ? <NotEnoughData /> : false}
|
cover={notEnoughData ? <NotEnoughData /> : isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,20 +10,24 @@ import {
|
|||||||
} from 'component/insights/components/LineChart/LineChart';
|
} from 'component/insights/components/LineChart/LineChart';
|
||||||
import { useTheme } from '@mui/material';
|
import { useTheme } from '@mui/material';
|
||||||
import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends';
|
import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends';
|
||||||
|
import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData';
|
||||||
|
|
||||||
interface IProjectHealthChartProps {
|
interface IProjectHealthChartProps {
|
||||||
projectFlagTrends: GroupedDataByProject<
|
projectFlagTrends: GroupedDataByProject<
|
||||||
InstanceInsightsSchema['projectFlagTrends']
|
InstanceInsightsSchema['projectFlagTrends']
|
||||||
>;
|
>;
|
||||||
isAggregate?: boolean;
|
isAggregate?: boolean;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProjectHealthChart: VFC<IProjectHealthChartProps> = ({
|
export const ProjectHealthChart: VFC<IProjectHealthChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
isAggregate,
|
isAggregate,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const projectsData = useProjectChartData(projectFlagTrends);
|
const projectsData = useProjectChartData(projectFlagTrends);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const placeholderData = usePlaceholderData();
|
||||||
|
|
||||||
const aggregateHealthData = useMemo(() => {
|
const aggregateHealthData = useMemo(() => {
|
||||||
const labels = Array.from(
|
const labels = Array.from(
|
||||||
@ -85,12 +89,19 @@ export const ProjectHealthChart: VFC<IProjectHealthChartProps> = ({
|
|||||||
};
|
};
|
||||||
}, [projectsData, theme]);
|
}, [projectsData, theme]);
|
||||||
|
|
||||||
const data = isAggregate ? aggregateHealthData : projectsData;
|
const aggregateOrProjectData = isAggregate
|
||||||
|
? aggregateHealthData
|
||||||
|
: projectsData;
|
||||||
const notEnoughData = useMemo(
|
const notEnoughData = useMemo(
|
||||||
() =>
|
() =>
|
||||||
projectsData.datasets.some((d) => d.data.length > 1) ? false : true,
|
!isLoading &&
|
||||||
[projectsData],
|
(projectsData.datasets.some((d) => d.data.length > 1)
|
||||||
|
? false
|
||||||
|
: true),
|
||||||
|
[projectsData, isLoading],
|
||||||
);
|
);
|
||||||
|
const data =
|
||||||
|
notEnoughData || isLoading ? placeholderData : aggregateOrProjectData;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LineChart
|
<LineChart
|
||||||
@ -104,7 +115,7 @@ export const ProjectHealthChart: VFC<IProjectHealthChartProps> = ({
|
|||||||
parsing: { yAxisKey: 'health', xAxisKey: 'date' },
|
parsing: { yAxisKey: 'health', xAxisKey: 'date' },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cover={notEnoughData ? <NotEnoughData /> : false}
|
cover={notEnoughData ? <NotEnoughData /> : isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -18,17 +18,21 @@ interface ITimeToProductionChartProps {
|
|||||||
InstanceInsightsSchema['projectFlagTrends']
|
InstanceInsightsSchema['projectFlagTrends']
|
||||||
>;
|
>;
|
||||||
isAggregate?: boolean;
|
isAggregate?: boolean;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TimeToProductionChart: VFC<ITimeToProductionChartProps> = ({
|
export const TimeToProductionChart: VFC<ITimeToProductionChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
isAggregate,
|
isAggregate,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const projectsDatasets = useProjectChartData(projectFlagTrends);
|
const projectsDatasets = useProjectChartData(projectFlagTrends);
|
||||||
const notEnoughData = useMemo(
|
const notEnoughData = useMemo(
|
||||||
() => !projectsDatasets.datasets.some((d) => d.data.length > 1),
|
() =>
|
||||||
[projectsDatasets],
|
!isLoading &&
|
||||||
|
!projectsDatasets.datasets.some((d) => d.data.length > 1),
|
||||||
|
[projectsDatasets, isLoading],
|
||||||
);
|
);
|
||||||
|
|
||||||
const aggregatedPerDay = useMemo(() => {
|
const aggregatedPerDay = useMemo(() => {
|
||||||
@ -62,7 +66,7 @@ export const TimeToProductionChart: VFC<ITimeToProductionChartProps> = ({
|
|||||||
const placeholderData = usePlaceholderData();
|
const placeholderData = usePlaceholderData();
|
||||||
return (
|
return (
|
||||||
<LineChart
|
<LineChart
|
||||||
data={notEnoughData ? placeholderData : data}
|
data={notEnoughData || isLoading ? placeholderData : data}
|
||||||
TooltipComponent={TimeToProductionTooltip}
|
TooltipComponent={TimeToProductionTooltip}
|
||||||
overrideOptions={
|
overrideOptions={
|
||||||
notEnoughData
|
notEnoughData
|
||||||
@ -74,7 +78,7 @@ export const TimeToProductionChart: VFC<ITimeToProductionChartProps> = ({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cover={notEnoughData ? <NotEnoughData /> : false}
|
cover={notEnoughData ? <NotEnoughData /> : isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,7 @@ export const UpdatesPerEnvironmentTypeChart: VFC<
|
|||||||
> = ({ environmentTypeTrends, isLoading }) => {
|
> = ({ environmentTypeTrends, isLoading }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const getEnvironmentTypeColor = useEnvironmentTypeColor();
|
const getEnvironmentTypeColor = useEnvironmentTypeColor();
|
||||||
const notEnoughData = environmentTypeTrends?.length < 2;
|
const notEnoughData = !isLoading && environmentTypeTrends?.length < 2;
|
||||||
const placeholderData = usePlaceholderData({ fill: true, type: 'double' });
|
const placeholderData = usePlaceholderData({ fill: true, type: 'double' });
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
|
@ -21,7 +21,7 @@ export const UsersChart: VFC<IUsersChartProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const notEnoughData = userTrends.length < 2;
|
const notEnoughData = !isLoading && userTrends.length < 2;
|
||||||
const placeholderData = usePlaceholderData({ fill: true, type: 'rising' });
|
const placeholderData = usePlaceholderData({ fill: true, type: 'rising' });
|
||||||
const data = useMemo(
|
const data = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -13,10 +13,12 @@ interface IUsersPerProjectChartProps {
|
|||||||
projectFlagTrends: GroupedDataByProject<
|
projectFlagTrends: GroupedDataByProject<
|
||||||
InstanceInsightsSchema['projectFlagTrends']
|
InstanceInsightsSchema['projectFlagTrends']
|
||||||
>;
|
>;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UsersPerProjectChart: VFC<IUsersPerProjectChartProps> = ({
|
export const UsersPerProjectChart: VFC<IUsersPerProjectChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
const placeholderData = usePlaceholderData({
|
const placeholderData = usePlaceholderData({
|
||||||
type: 'constant',
|
type: 'constant',
|
||||||
@ -24,20 +26,22 @@ export const UsersPerProjectChart: VFC<IUsersPerProjectChartProps> = ({
|
|||||||
|
|
||||||
const data = useProjectChartData(projectFlagTrends);
|
const data = useProjectChartData(projectFlagTrends);
|
||||||
const notEnoughData = useMemo(
|
const notEnoughData = useMemo(
|
||||||
() => (data.datasets.some((d) => d.data.length > 1) ? false : true),
|
() =>
|
||||||
[data],
|
!isLoading &&
|
||||||
|
(data.datasets.some((d) => d.data.length > 1) ? false : true),
|
||||||
|
[data, isLoading],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LineChart
|
<LineChart
|
||||||
data={notEnoughData ? placeholderData : data}
|
data={notEnoughData || isLoading ? placeholderData : data}
|
||||||
overrideOptions={{
|
overrideOptions={{
|
||||||
parsing: {
|
parsing: {
|
||||||
yAxisKey: 'users',
|
yAxisKey: 'users',
|
||||||
xAxisKey: 'date',
|
xAxisKey: 'date',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
cover={notEnoughData ? <NotEnoughData /> : false}
|
cover={notEnoughData ? <NotEnoughData /> : isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -68,17 +68,21 @@ const StyledIcon = styled(Icon)(({ theme }) => ({
|
|||||||
interface IFlagStatsProps {
|
interface IFlagStatsProps {
|
||||||
count: number;
|
count: number;
|
||||||
flagsPerUser?: string;
|
flagsPerUser?: string;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FlagStats: React.FC<IFlagStatsProps> = ({
|
export const FlagStats: React.FC<IFlagStatsProps> = ({
|
||||||
count,
|
count,
|
||||||
flagsPerUser,
|
flagsPerUser,
|
||||||
|
isLoading,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyledRingContainer>
|
<StyledRingContainer>
|
||||||
<StyledRing>
|
<StyledRing>
|
||||||
<StyledRingContent>{count}</StyledRingContent>
|
<StyledRingContent>
|
||||||
|
{isLoading ? '' : count}
|
||||||
|
</StyledRingContent>
|
||||||
</StyledRing>
|
</StyledRing>
|
||||||
</StyledRingContainer>
|
</StyledRingContainer>
|
||||||
|
|
||||||
|
@ -70,9 +70,21 @@ interface IUserStatsProps {
|
|||||||
count: number;
|
count: number;
|
||||||
active?: number;
|
active?: number;
|
||||||
inactive?: number;
|
inactive?: number;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserStats: FC<IUserStatsProps> = ({ count, active, inactive }) => {
|
const StyledLoadingSkeleton = styled(Box)(() => ({
|
||||||
|
'&:before': {
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const UserStats: FC<IUserStatsProps> = ({
|
||||||
|
count,
|
||||||
|
active,
|
||||||
|
inactive,
|
||||||
|
isLoading,
|
||||||
|
}) => {
|
||||||
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
||||||
const showDistribution =
|
const showDistribution =
|
||||||
showInactiveUsers && active !== undefined && inactive !== undefined;
|
showInactiveUsers && active !== undefined && inactive !== undefined;
|
||||||
@ -83,9 +95,19 @@ export const UserStats: FC<IUserStatsProps> = ({ count, active, inactive }) => {
|
|||||||
<StyledUserContainer>
|
<StyledUserContainer>
|
||||||
<StyledUserBox>
|
<StyledUserBox>
|
||||||
<StyledUserCount variant='h2'>
|
<StyledUserCount variant='h2'>
|
||||||
{Number.parseInt(`${count}`, 10) === count
|
<ConditionallyRender
|
||||||
? count
|
condition={isLoading !== true}
|
||||||
: count.toFixed(2)}
|
show={
|
||||||
|
Number.parseInt(`${count}`, 10) === count
|
||||||
|
? count
|
||||||
|
: count.toFixed(2)
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<StyledLoadingSkeleton className='skeleton'>
|
||||||
|
|
||||||
|
</StyledLoadingSkeleton>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</StyledUserCount>
|
</StyledUserCount>
|
||||||
</StyledUserBox>
|
</StyledUserBox>
|
||||||
<StyledCustomShadow />
|
<StyledCustomShadow />
|
||||||
|
Loading…
Reference in New Issue
Block a user