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 { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
|
||||
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 { BillingHistory } from './BillingHistory/BillingHistory.tsx';
|
||||
import useInvoices from 'hooks/api/getters/useInvoices/useInvoices';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { BillingInvoices } from './BillingInvoices/BillingInvoices.tsx';
|
||||
|
||||
export const Billing = () => {
|
||||
const { isBilling, refetchInstanceStatus, refresh, loading } =
|
||||
useInstanceStatus();
|
||||
const { invoices } = useInvoices();
|
||||
const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
|
||||
|
||||
useEffect(() => {
|
||||
const hardRefresh = async () => {
|
||||
@ -22,6 +25,21 @@ export const Billing = () => {
|
||||
hardRefresh();
|
||||
}, [refetchInstanceStatus, refresh]);
|
||||
|
||||
if (trafficBillingDisplay) {
|
||||
return (
|
||||
<Box
|
||||
sx={(theme) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(4),
|
||||
})}
|
||||
>
|
||||
<BillingDashboard />
|
||||
<BillingInvoices />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageContent header='Billing' isLoading={loading}>
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
import { Grid } from '@mui/material';
|
||||
import { BillingInformation } from './BillingInformation/BillingInformation.tsx';
|
||||
import { BillingPlan } from './BillingPlan/BillingPlan.tsx';
|
||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
||||
|
||||
export const BillingDashboard = () => {
|
||||
const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
|
||||
|
||||
return (
|
||||
<Grid container spacing={4}>
|
||||
<Grid container spacing={trafficBillingDisplay ? 2 : 4}>
|
||||
<BillingInformation />
|
||||
<BillingPlan />
|
||||
</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 { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { InstanceState } from 'interfaces/instance';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
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),
|
||||
height: '100%',
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
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 }) => ({
|
||||
marginBottom: theme.spacing(4),
|
||||
}));
|
||||
@ -36,11 +47,15 @@ export const BillingInformation = () => {
|
||||
uiConfig: { billing },
|
||||
} = useUiConfig();
|
||||
const isPAYG = billing === 'pay-as-you-go';
|
||||
const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
|
||||
const StyledWrapper = trafficBillingDisplay
|
||||
? StyledInfoBox
|
||||
: LegacyStyledInfoBox;
|
||||
|
||||
if (!instanceStatus)
|
||||
return (
|
||||
<Grid item xs={12} md={5}>
|
||||
<StyledInfoBox data-loading sx={{ flex: 1, height: '400px' }} />
|
||||
<StyledWrapper data-loading sx={{ flex: 1, height: '400px' }} />
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@ -50,7 +65,7 @@ export const BillingInformation = () => {
|
||||
|
||||
return (
|
||||
<Grid item xs={12} md={5}>
|
||||
<StyledInfoBox>
|
||||
<StyledWrapper>
|
||||
<StyledTitle variant='body1'>Billing information</StyledTitle>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(isCustomBilling)}
|
||||
@ -89,7 +104,7 @@ export const BillingInformation = () => {
|
||||
</a>{' '}
|
||||
for any clarification
|
||||
</StyledInfoLabel>
|
||||
</StyledInfoBox>
|
||||
</StyledWrapper>
|
||||
</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 { InstancePlan, InstanceState } from 'interfaces/instance';
|
||||
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 { BillingDetails } from './BillingDetails.tsx';
|
||||
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_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_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),
|
||||
height: '100%',
|
||||
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 }) => ({
|
||||
fontSize: '3.25rem',
|
||||
lineHeight: 1,
|
||||
@ -63,6 +74,7 @@ export const BillingPlan = () => {
|
||||
const {
|
||||
uiConfig: { billing },
|
||||
} = useUiConfig();
|
||||
const trafficBillingDisplay = useUiFlag('trafficBillingDisplay');
|
||||
const { instanceStatus } = useInstanceStatus();
|
||||
|
||||
const isPro =
|
||||
@ -70,10 +82,14 @@ export const BillingPlan = () => {
|
||||
const isPAYG = billing === 'pay-as-you-go';
|
||||
const isEnterpriseConsumption = billing === 'enterprise-consumption';
|
||||
|
||||
const StyledWrapper = trafficBillingDisplay
|
||||
? StyledPlanBox
|
||||
: LegacyStyledPlanBox;
|
||||
|
||||
if (!instanceStatus)
|
||||
return (
|
||||
<Grid item xs={12} md={7}>
|
||||
<StyledPlanBox data-loading sx={{ flex: 1, height: '400px' }} />
|
||||
<StyledWrapper data-loading sx={{ flex: 1, height: '400px' }} />
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@ -85,7 +101,7 @@ export const BillingPlan = () => {
|
||||
|
||||
return (
|
||||
<Grid item xs={12} md={7}>
|
||||
<StyledPlanBox>
|
||||
<StyledWrapper>
|
||||
<ConditionallyRender
|
||||
condition={inactive}
|
||||
show={
|
||||
@ -161,7 +177,7 @@ export const BillingPlan = () => {
|
||||
isPAYG={isPAYG}
|
||||
isEnterpriseConsumption={isEnterpriseConsumption}
|
||||
/>
|
||||
</StyledPlanBox>
|
||||
</StyledWrapper>
|
||||
</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;
|
||||
globalChangeRequestList?: boolean;
|
||||
flagsUiFilterRefactor?: boolean;
|
||||
trafficBillingDisplay?: boolean;
|
||||
milestoneProgression?: boolean;
|
||||
};
|
||||
|
||||
|
||||
@ -61,6 +61,7 @@ export type IFlagKey =
|
||||
| 'globalChangeRequestList'
|
||||
| 'newUiConfigService'
|
||||
| 'flagsUiFilterRefactor'
|
||||
| 'trafficBillingDisplay'
|
||||
| 'milestoneProgression';
|
||||
|
||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||
@ -278,6 +279,10 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_FLAGS_UI_FILTER_REFACTOR,
|
||||
false,
|
||||
),
|
||||
trafficBillingDisplay: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_TRAFFIC_BILLING_DISPLAY,
|
||||
false,
|
||||
),
|
||||
milestoneProgression: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_MILESTONE_PROGRESSION,
|
||||
false,
|
||||
|
||||
@ -57,6 +57,7 @@ process.nextTick(async () => {
|
||||
globalChangeRequestList: true,
|
||||
newUiConfigService: true,
|
||||
flagsUiFilterRefactor: true,
|
||||
trafficBillingDisplay: true,
|
||||
milestoneProgression: true,
|
||||
},
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user