mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: flag traffic billing display feature (#10718)
Feature flag and initial changes in Billing UI
This commit is contained in:
		
							parent
							
								
									df67c041fc
								
							
						
					
					
						commit
						9b5324ac92
					
				@ -4,15 +4,18 @@ import { ADMIN } from 'component/providers/AccessProvider/permissions';
 | 
				
			|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
 | 
					import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
 | 
				
			||||||
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
					import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
				
			||||||
import { Alert } from '@mui/material';
 | 
					import { Alert, Box } from '@mui/material';
 | 
				
			||||||
import { BillingDashboard } from './BillingDashboard/BillingDashboard.tsx';
 | 
					import { BillingDashboard } from './BillingDashboard/BillingDashboard.tsx';
 | 
				
			||||||
import { BillingHistory } from './BillingHistory/BillingHistory.tsx';
 | 
					import { BillingHistory } from './BillingHistory/BillingHistory.tsx';
 | 
				
			||||||
import useInvoices from 'hooks/api/getters/useInvoices/useInvoices';
 | 
					import useInvoices from 'hooks/api/getters/useInvoices/useInvoices';
 | 
				
			||||||
 | 
					import { useUiFlag } from 'hooks/useUiFlag';
 | 
				
			||||||
 | 
					import { BillingInvoices } from './BillingInvoices/BillingInvoices.tsx';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Billing = () => {
 | 
					export const Billing = () => {
 | 
				
			||||||
    const { isBilling, refetchInstanceStatus, refresh, loading } =
 | 
					    const { isBilling, refetchInstanceStatus, refresh, loading } =
 | 
				
			||||||
        useInstanceStatus();
 | 
					        useInstanceStatus();
 | 
				
			||||||
    const { invoices } = useInvoices();
 | 
					    const { invoices } = useInvoices();
 | 
				
			||||||
 | 
					    const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        const hardRefresh = async () => {
 | 
					        const hardRefresh = async () => {
 | 
				
			||||||
@ -22,6 +25,21 @@ export const Billing = () => {
 | 
				
			|||||||
        hardRefresh();
 | 
					        hardRefresh();
 | 
				
			||||||
    }, [refetchInstanceStatus, refresh]);
 | 
					    }, [refetchInstanceStatus, refresh]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (trafficBillingDisplay) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Box
 | 
				
			||||||
 | 
					                sx={(theme) => ({
 | 
				
			||||||
 | 
					                    display: 'flex',
 | 
				
			||||||
 | 
					                    flexDirection: 'column',
 | 
				
			||||||
 | 
					                    gap: theme.spacing(4),
 | 
				
			||||||
 | 
					                })}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                <BillingDashboard />
 | 
				
			||||||
 | 
					                <BillingInvoices />
 | 
				
			||||||
 | 
					            </Box>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
            <PageContent header='Billing' isLoading={loading}>
 | 
					            <PageContent header='Billing' isLoading={loading}>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,13 @@
 | 
				
			|||||||
import { Grid } from '@mui/material';
 | 
					import { Grid } from '@mui/material';
 | 
				
			||||||
import { BillingInformation } from './BillingInformation/BillingInformation.tsx';
 | 
					import { BillingInformation } from './BillingInformation/BillingInformation.tsx';
 | 
				
			||||||
import { BillingPlan } from './BillingPlan/BillingPlan.tsx';
 | 
					import { BillingPlan } from './BillingPlan/BillingPlan.tsx';
 | 
				
			||||||
 | 
					import { useUiFlag } from 'hooks/useUiFlag.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const BillingDashboard = () => {
 | 
					export const BillingDashboard = () => {
 | 
				
			||||||
 | 
					    const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Grid container spacing={4}>
 | 
					        <Grid container spacing={trafficBillingDisplay ? 2 : 4}>
 | 
				
			||||||
            <BillingInformation />
 | 
					            <BillingInformation />
 | 
				
			||||||
            <BillingPlan />
 | 
					            <BillingPlan />
 | 
				
			||||||
        </Grid>
 | 
					        </Grid>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,28 @@
 | 
				
			|||||||
import { Alert, Divider, Grid, styled, Typography } from '@mui/material';
 | 
					import { Alert, Divider, Grid, Paper, styled, Typography } from '@mui/material';
 | 
				
			||||||
import { BillingInformationButton } from './BillingInformationButton/BillingInformationButton.tsx';
 | 
					import { BillingInformationButton } from './BillingInformationButton/BillingInformationButton.tsx';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import { InstanceState } from 'interfaces/instance';
 | 
					import { InstanceState } from 'interfaces/instance';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
					import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
				
			||||||
 | 
					import { useUiFlag } from 'hooks/useUiFlag.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledInfoBox = styled('aside')(({ theme }) => ({
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated remove with `trafficBillingDisplay` flag
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const LegacyStyledInfoBox = styled('aside')(({ theme }) => ({
 | 
				
			||||||
    padding: theme.spacing(4),
 | 
					    padding: theme.spacing(4),
 | 
				
			||||||
    height: '100%',
 | 
					    height: '100%',
 | 
				
			||||||
    borderRadius: theme.shape.borderRadiusLarge,
 | 
					    borderRadius: theme.shape.borderRadiusLarge,
 | 
				
			||||||
    backgroundColor: theme.palette.background.elevation2,
 | 
					    backgroundColor: theme.palette.background.elevation2,
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledInfoBox = styled(Paper)(({ theme }) => ({
 | 
				
			||||||
 | 
					    padding: theme.spacing(4),
 | 
				
			||||||
 | 
					    height: '100%',
 | 
				
			||||||
 | 
					    borderRadius: theme.shape.borderRadiusLarge,
 | 
				
			||||||
 | 
					    backgroundColor: theme.palette.background.paper,
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledTitle = styled(Typography)(({ theme }) => ({
 | 
					const StyledTitle = styled(Typography)(({ theme }) => ({
 | 
				
			||||||
    marginBottom: theme.spacing(4),
 | 
					    marginBottom: theme.spacing(4),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
@ -36,11 +47,15 @@ export const BillingInformation = () => {
 | 
				
			|||||||
        uiConfig: { billing },
 | 
					        uiConfig: { billing },
 | 
				
			||||||
    } = useUiConfig();
 | 
					    } = useUiConfig();
 | 
				
			||||||
    const isPAYG = billing === 'pay-as-you-go';
 | 
					    const isPAYG = billing === 'pay-as-you-go';
 | 
				
			||||||
 | 
					    const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
 | 
				
			||||||
 | 
					    const StyledWrapper = trafficBillingDisplay
 | 
				
			||||||
 | 
					        ? StyledInfoBox
 | 
				
			||||||
 | 
					        : LegacyStyledInfoBox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!instanceStatus)
 | 
					    if (!instanceStatus)
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <Grid item xs={12} md={5}>
 | 
					            <Grid item xs={12} md={5}>
 | 
				
			||||||
                <StyledInfoBox data-loading sx={{ flex: 1, height: '400px' }} />
 | 
					                <StyledWrapper data-loading sx={{ flex: 1, height: '400px' }} />
 | 
				
			||||||
            </Grid>
 | 
					            </Grid>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,7 +65,7 @@ export const BillingInformation = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Grid item xs={12} md={5}>
 | 
					        <Grid item xs={12} md={5}>
 | 
				
			||||||
            <StyledInfoBox>
 | 
					            <StyledWrapper>
 | 
				
			||||||
                <StyledTitle variant='body1'>Billing information</StyledTitle>
 | 
					                <StyledTitle variant='body1'>Billing information</StyledTitle>
 | 
				
			||||||
                <ConditionallyRender
 | 
					                <ConditionallyRender
 | 
				
			||||||
                    condition={Boolean(isCustomBilling)}
 | 
					                    condition={Boolean(isCustomBilling)}
 | 
				
			||||||
@ -89,7 +104,7 @@ export const BillingInformation = () => {
 | 
				
			|||||||
                    </a>{' '}
 | 
					                    </a>{' '}
 | 
				
			||||||
                    for any clarification
 | 
					                    for any clarification
 | 
				
			||||||
                </StyledInfoLabel>
 | 
					                </StyledInfoLabel>
 | 
				
			||||||
            </StyledInfoBox>
 | 
					            </StyledWrapper>
 | 
				
			||||||
        </Grid>
 | 
					        </Grid>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { Alert, Grid, styled } from '@mui/material';
 | 
					import { Alert, Grid, Paper, styled } from '@mui/material';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
import { InstancePlan, InstanceState } from 'interfaces/instance';
 | 
					import { InstancePlan, InstanceState } from 'interfaces/instance';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
@ -8,6 +8,7 @@ import { GridCol } from 'component/common/GridCol/GridCol';
 | 
				
			|||||||
import { Badge } from 'component/common/Badge/Badge';
 | 
					import { Badge } from 'component/common/Badge/Badge';
 | 
				
			||||||
import { BillingDetails } from './BillingDetails.tsx';
 | 
					import { BillingDetails } from './BillingDetails.tsx';
 | 
				
			||||||
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
					import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
 | 
				
			||||||
 | 
					import { useUiFlag } from 'hooks/useUiFlag.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const BILLING_PRO_BASE_PRICE = 80;
 | 
					export const BILLING_PRO_BASE_PRICE = 80;
 | 
				
			||||||
export const BILLING_PRO_SEAT_PRICE = 15;
 | 
					export const BILLING_PRO_SEAT_PRICE = 15;
 | 
				
			||||||
@ -18,7 +19,10 @@ export const BILLING_PAYG_DEFAULT_MINIMUM_SEATS = 5;
 | 
				
			|||||||
export const BILLING_PRO_DEFAULT_INCLUDED_SEATS = 5;
 | 
					export const BILLING_PRO_DEFAULT_INCLUDED_SEATS = 5;
 | 
				
			||||||
export const BILLING_INCLUDED_REQUESTS = 53_000_000;
 | 
					export const BILLING_INCLUDED_REQUESTS = 53_000_000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledPlanBox = styled('aside')(({ theme }) => ({
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated remove with `trafficBillingDisplay` flag
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const LegacyStyledPlanBox = styled('aside')(({ theme }) => ({
 | 
				
			||||||
    padding: theme.spacing(2.5),
 | 
					    padding: theme.spacing(2.5),
 | 
				
			||||||
    height: '100%',
 | 
					    height: '100%',
 | 
				
			||||||
    borderRadius: theme.shape.borderRadiusLarge,
 | 
					    borderRadius: theme.shape.borderRadiusLarge,
 | 
				
			||||||
@ -28,6 +32,13 @@ const StyledPlanBox = styled('aside')(({ theme }) => ({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledPlanBox = styled(Paper)(({ theme }) => ({
 | 
				
			||||||
 | 
					    padding: theme.spacing(4),
 | 
				
			||||||
 | 
					    height: '100%',
 | 
				
			||||||
 | 
					    borderRadius: theme.shape.borderRadiusLarge,
 | 
				
			||||||
 | 
					    backgroundColor: theme.palette.background.paper,
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledPlanSpan = styled('span')(({ theme }) => ({
 | 
					const StyledPlanSpan = styled('span')(({ theme }) => ({
 | 
				
			||||||
    fontSize: '3.25rem',
 | 
					    fontSize: '3.25rem',
 | 
				
			||||||
    lineHeight: 1,
 | 
					    lineHeight: 1,
 | 
				
			||||||
@ -63,6 +74,7 @@ export const BillingPlan = () => {
 | 
				
			|||||||
    const {
 | 
					    const {
 | 
				
			||||||
        uiConfig: { billing },
 | 
					        uiConfig: { billing },
 | 
				
			||||||
    } = useUiConfig();
 | 
					    } = useUiConfig();
 | 
				
			||||||
 | 
					    const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
 | 
				
			||||||
    const { instanceStatus } = useInstanceStatus();
 | 
					    const { instanceStatus } = useInstanceStatus();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const isPro =
 | 
					    const isPro =
 | 
				
			||||||
@ -70,10 +82,14 @@ export const BillingPlan = () => {
 | 
				
			|||||||
    const isPAYG = billing === 'pay-as-you-go';
 | 
					    const isPAYG = billing === 'pay-as-you-go';
 | 
				
			||||||
    const isEnterpriseConsumption = billing === 'enterprise-consumption';
 | 
					    const isEnterpriseConsumption = billing === 'enterprise-consumption';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const StyledWrapper = trafficBillingDisplay
 | 
				
			||||||
 | 
					        ? StyledPlanBox
 | 
				
			||||||
 | 
					        : LegacyStyledPlanBox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!instanceStatus)
 | 
					    if (!instanceStatus)
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <Grid item xs={12} md={7}>
 | 
					            <Grid item xs={12} md={7}>
 | 
				
			||||||
                <StyledPlanBox data-loading sx={{ flex: 1, height: '400px' }} />
 | 
					                <StyledWrapper data-loading sx={{ flex: 1, height: '400px' }} />
 | 
				
			||||||
            </Grid>
 | 
					            </Grid>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,7 +101,7 @@ export const BillingPlan = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Grid item xs={12} md={7}>
 | 
					        <Grid item xs={12} md={7}>
 | 
				
			||||||
            <StyledPlanBox>
 | 
					            <StyledWrapper>
 | 
				
			||||||
                <ConditionallyRender
 | 
					                <ConditionallyRender
 | 
				
			||||||
                    condition={inactive}
 | 
					                    condition={inactive}
 | 
				
			||||||
                    show={
 | 
					                    show={
 | 
				
			||||||
@ -161,7 +177,7 @@ export const BillingPlan = () => {
 | 
				
			|||||||
                    isPAYG={isPAYG}
 | 
					                    isPAYG={isPAYG}
 | 
				
			||||||
                    isEnterpriseConsumption={isEnterpriseConsumption}
 | 
					                    isEnterpriseConsumption={isEnterpriseConsumption}
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
            </StyledPlanBox>
 | 
					            </StyledWrapper>
 | 
				
			||||||
        </Grid>
 | 
					        </Grid>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import { Box, styled, Typography } from '@mui/material';
 | 
				
			||||||
 | 
					import type { FC } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledContainer = styled(Box)(({ theme }) => ({
 | 
				
			||||||
 | 
					    display: 'flex',
 | 
				
			||||||
 | 
					    flexDirection: 'column',
 | 
				
			||||||
 | 
					    gap: theme.spacing(3),
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledHeader = styled(Typography)(({ theme }) => ({
 | 
				
			||||||
 | 
					    fontSize: theme.fontSizes.mainHeader,
 | 
				
			||||||
 | 
					    fontWeight: theme.fontWeight.semi,
 | 
				
			||||||
 | 
					    color: theme.palette.text.primary,
 | 
				
			||||||
 | 
					    marginBottom: theme.spacing(2),
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BillingInvoicesProps = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BillingInvoices: FC<BillingInvoicesProps> = () => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <StyledContainer>
 | 
				
			||||||
 | 
					            <StyledHeader>Usage and invoices</StyledHeader>
 | 
				
			||||||
 | 
					        </StyledContainer>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -89,6 +89,7 @@ export type UiFlags = {
 | 
				
			|||||||
    newStrategyModal?: boolean;
 | 
					    newStrategyModal?: boolean;
 | 
				
			||||||
    globalChangeRequestList?: boolean;
 | 
					    globalChangeRequestList?: boolean;
 | 
				
			||||||
    flagsUiFilterRefactor?: boolean;
 | 
					    flagsUiFilterRefactor?: boolean;
 | 
				
			||||||
 | 
					    trafficBillingDisplay?: boolean;
 | 
				
			||||||
    milestoneProgression?: boolean;
 | 
					    milestoneProgression?: boolean;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ export type IFlagKey =
 | 
				
			|||||||
    | 'globalChangeRequestList'
 | 
					    | 'globalChangeRequestList'
 | 
				
			||||||
    | 'newUiConfigService'
 | 
					    | 'newUiConfigService'
 | 
				
			||||||
    | 'flagsUiFilterRefactor'
 | 
					    | 'flagsUiFilterRefactor'
 | 
				
			||||||
 | 
					    | 'trafficBillingDisplay'
 | 
				
			||||||
    | 'milestoneProgression';
 | 
					    | 'milestoneProgression';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
 | 
					export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
 | 
				
			||||||
@ -278,6 +279,10 @@ const flags: IFlags = {
 | 
				
			|||||||
        process.env.UNLEASH_EXPERIMENTAL_FLAGS_UI_FILTER_REFACTOR,
 | 
					        process.env.UNLEASH_EXPERIMENTAL_FLAGS_UI_FILTER_REFACTOR,
 | 
				
			||||||
        false,
 | 
					        false,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
 | 
					    trafficBillingDisplay: parseEnvVarBoolean(
 | 
				
			||||||
 | 
					        process.env.UNLEASH_EXPERIMENTAL_TRAFFIC_BILLING_DISPLAY,
 | 
				
			||||||
 | 
					        false,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
    milestoneProgression: parseEnvVarBoolean(
 | 
					    milestoneProgression: parseEnvVarBoolean(
 | 
				
			||||||
        process.env.UNLEASH_EXPERIMENTAL_MILESTONE_PROGRESSION,
 | 
					        process.env.UNLEASH_EXPERIMENTAL_MILESTONE_PROGRESSION,
 | 
				
			||||||
        false,
 | 
					        false,
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@ process.nextTick(async () => {
 | 
				
			|||||||
                        globalChangeRequestList: true,
 | 
					                        globalChangeRequestList: true,
 | 
				
			||||||
                        newUiConfigService: true,
 | 
					                        newUiConfigService: true,
 | 
				
			||||||
                        flagsUiFilterRefactor: true,
 | 
					                        flagsUiFilterRefactor: true,
 | 
				
			||||||
 | 
					                        trafficBillingDisplay: true,
 | 
				
			||||||
                        milestoneProgression: true,
 | 
					                        milestoneProgression: true,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user