mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
fix: show previous invoices page if UNLEASH_CLOUD is falsy (#1094)
* fix: restore previous invoices page * fix: show previous invoices page if UNLEASH_CLOUD is falsy * fix: use correct amountFormatted invoice field name
This commit is contained in:
parent
51e5939f68
commit
4fb0be3710
@ -0,0 +1,19 @@
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import InvoiceAdminPage from 'component/admin/invoice/InvoiceAdminPage';
|
||||
|
||||
const FlaggedBillingRedirect = () => {
|
||||
const { uiConfig, loading } = useUiConfig();
|
||||
|
||||
if (loading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!uiConfig.flags.UNLEASH_CLOUD) {
|
||||
return <InvoiceAdminPage />;
|
||||
}
|
||||
|
||||
return <Navigate to="/admin/billing" replace />;
|
||||
};
|
||||
|
||||
export default FlaggedBillingRedirect;
|
@ -1,7 +0,0 @@
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
const RedirectAdminInvoices = () => {
|
||||
return <Navigate to="/admin/billing" replace />;
|
||||
};
|
||||
|
||||
export default RedirectAdminInvoices;
|
25
frontend/src/component/admin/invoice/InvoiceAdminPage.tsx
Normal file
25
frontend/src/component/admin/invoice/InvoiceAdminPage.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { useContext } from 'react';
|
||||
import InvoiceList from './InvoiceList';
|
||||
import AccessContext from 'contexts/AccessContext';
|
||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { Alert } from '@mui/material';
|
||||
|
||||
const InvoiceAdminPage = () => {
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
return (
|
||||
<div>
|
||||
<ConditionallyRender
|
||||
condition={hasAccess(ADMIN)}
|
||||
show={<InvoiceList />}
|
||||
elseShow={
|
||||
<Alert severity="error">
|
||||
You need to be instance admin to access this section.
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvoiceAdminPage;
|
122
frontend/src/component/admin/invoice/InvoiceList.tsx
Normal file
122
frontend/src/component/admin/invoice/InvoiceList.tsx
Normal file
@ -0,0 +1,122 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Table,
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableRow,
|
||||
TableCell,
|
||||
Button,
|
||||
} from '@mui/material';
|
||||
import OpenInNew from '@mui/icons-material/OpenInNew';
|
||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import useInvoices from 'hooks/api/getters/useInvoices/useInvoices';
|
||||
import { IInvoice } from 'interfaces/invoice';
|
||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||
import { formatDateYMD } from 'utils/formatDate';
|
||||
|
||||
const PORTAL_URL = formatApiPath('api/admin/invoices/portal');
|
||||
|
||||
const InvoiceList = () => {
|
||||
const { refetchInvoices, invoices } = useInvoices();
|
||||
const [isLoaded, setLoaded] = useState(false);
|
||||
const { locationSettings } = useLocationSettings();
|
||||
|
||||
useEffect(() => {
|
||||
refetchInvoices();
|
||||
setLoaded(true);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ConditionallyRender
|
||||
condition={invoices.length > 0}
|
||||
show={
|
||||
<PageContent
|
||||
header={
|
||||
<PageHeader
|
||||
title="Invoices"
|
||||
actions={
|
||||
<Button
|
||||
href={PORTAL_URL}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
endIcon={<OpenInNew />}
|
||||
>
|
||||
Billing portal
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Amount</TableCell>
|
||||
<TableCell>Status</TableCell>
|
||||
<TableCell>Due date</TableCell>
|
||||
<TableCell>PDF</TableCell>
|
||||
<TableCell>Link</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{invoices.map((item: IInvoice) => (
|
||||
<TableRow
|
||||
key={item.invoiceURL}
|
||||
style={{
|
||||
backgroundColor:
|
||||
item.status === 'past-due'
|
||||
? '#ff9194'
|
||||
: 'inherit',
|
||||
}}
|
||||
>
|
||||
<TableCell
|
||||
style={{ textAlign: 'left' }}
|
||||
>
|
||||
{item.amountFormatted}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
style={{ textAlign: 'left' }}
|
||||
>
|
||||
{item.status}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
style={{ textAlign: 'left' }}
|
||||
>
|
||||
{item.dueDate &&
|
||||
formatDateYMD(
|
||||
item.dueDate,
|
||||
locationSettings.locale
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
style={{ textAlign: 'left' }}
|
||||
>
|
||||
<a href={item.invoicePDF}>PDF</a>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
style={{ textAlign: 'left' }}
|
||||
>
|
||||
<a
|
||||
href={item.invoiceURL}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Payment link
|
||||
</a>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</PageContent>
|
||||
}
|
||||
elseShow={<div>{isLoaded && 'No invoices to show.'}</div>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
export default InvoiceList;
|
@ -23,7 +23,6 @@ import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions
|
||||
import { useStyles } from './Header.styles';
|
||||
import classNames from 'classnames';
|
||||
import { useId } from 'hooks/useId';
|
||||
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
|
||||
import { IRoute } from 'interfaces/route';
|
||||
|
||||
const Header: VFC = () => {
|
||||
@ -37,6 +36,7 @@ const Header: VFC = () => {
|
||||
const { permissions } = useAuthPermissions();
|
||||
const {
|
||||
uiConfig: { links, name, flags },
|
||||
isOss,
|
||||
} = useUiConfig();
|
||||
const smallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const { classes: styles } = useStyles();
|
||||
@ -57,15 +57,18 @@ const Header: VFC = () => {
|
||||
}
|
||||
}, [permissions]);
|
||||
|
||||
const { isBilling } = useInstanceStatus();
|
||||
const routes = getRoutes();
|
||||
|
||||
const filterByEnterprise = (route: IRoute): boolean => {
|
||||
return !route.menu.isEnterprise || !isOss();
|
||||
};
|
||||
|
||||
const filteredMainRoutes = {
|
||||
mainNavRoutes: routes.mainNavRoutes.filter(filterByFlags(flags)),
|
||||
mobileRoutes: routes.mobileRoutes.filter(filterByFlags(flags)),
|
||||
adminRoutes: routes.adminRoutes
|
||||
.filter(filterByFlags(flags))
|
||||
.filter(filterByBilling(isBilling)),
|
||||
.filter(filterByEnterprise),
|
||||
};
|
||||
|
||||
if (smallScreen) {
|
||||
@ -196,7 +199,4 @@ const Header: VFC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const filterByBilling = (isBilling?: boolean) => (route: IRoute) =>
|
||||
!route.menu.isBilling || isBilling;
|
||||
|
||||
export default Header;
|
||||
|
@ -411,10 +411,7 @@ exports[`returns all baseRoutes 1`] = `
|
||||
},
|
||||
{
|
||||
"component": [Function],
|
||||
"menu": {
|
||||
"adminSettings": true,
|
||||
"isBilling": true,
|
||||
},
|
||||
"menu": {},
|
||||
"parent": "/admin",
|
||||
"path": "/admin/billing",
|
||||
"title": "Billing",
|
||||
@ -422,7 +419,10 @@ exports[`returns all baseRoutes 1`] = `
|
||||
},
|
||||
{
|
||||
"component": [Function],
|
||||
"menu": {},
|
||||
"menu": {
|
||||
"adminSettings": true,
|
||||
"isEnterprise": true,
|
||||
},
|
||||
"parent": "/admin",
|
||||
"path": "/admin-invoices",
|
||||
"title": "Invoices",
|
||||
|
@ -7,7 +7,6 @@ import Admin from 'component/admin';
|
||||
import AdminApi from 'component/admin/api';
|
||||
import AdminUsers from 'component/admin/users/UsersAdmin';
|
||||
import { AuthSettings } from 'component/admin/auth/AuthSettings';
|
||||
import { Billing } from 'component/admin/billing/Billing';
|
||||
import Login from 'component/user/Login/Login';
|
||||
import { C, EEA, P, RE, SE } from 'component/common/flags';
|
||||
import { NewUser } from 'component/user/NewUser/NewUser';
|
||||
@ -50,8 +49,9 @@ import { EditSegment } from 'component/segments/EditSegment/EditSegment';
|
||||
import { IRoute } from 'interfaces/route';
|
||||
import { EnvironmentTable } from 'component/environments/EnvironmentTable/EnvironmentTable';
|
||||
import { SegmentTable } from 'component/segments/SegmentTable/SegmentTable';
|
||||
import RedirectAdminInvoices from 'component/admin/billing/RedirectAdminInvoices/RedirectAdminInvoices';
|
||||
import FlaggedBillingRedirect from 'component/admin/billing/FlaggedBillingRedirect/FlaggedBillingRedirect';
|
||||
import { FeaturesArchiveTable } from '../archive/FeaturesArchiveTable';
|
||||
import { Billing } from 'component/admin/billing/Billing';
|
||||
|
||||
export const routes: IRoute[] = [
|
||||
// Splash
|
||||
@ -462,15 +462,15 @@ export const routes: IRoute[] = [
|
||||
title: 'Billing',
|
||||
component: Billing,
|
||||
type: 'protected',
|
||||
menu: { adminSettings: true, isBilling: true },
|
||||
menu: {},
|
||||
},
|
||||
{
|
||||
path: '/admin-invoices',
|
||||
parent: '/admin',
|
||||
title: 'Invoices',
|
||||
component: RedirectAdminInvoices,
|
||||
component: FlaggedBillingRedirect,
|
||||
type: 'protected',
|
||||
menu: {},
|
||||
menu: { adminSettings: true, isEnterprise: true },
|
||||
},
|
||||
{
|
||||
path: '/admin',
|
||||
|
8
frontend/src/interfaces/invoice.ts
Normal file
8
frontend/src/interfaces/invoice.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface IInvoice {
|
||||
amountFormatted: string;
|
||||
invoicePDF: string;
|
||||
invoiceURL: string;
|
||||
paid: boolean;
|
||||
status: string;
|
||||
dueDate?: Date;
|
||||
}
|
@ -17,5 +17,5 @@ interface IRouteMenu {
|
||||
mobile?: boolean;
|
||||
advanced?: boolean;
|
||||
adminSettings?: boolean;
|
||||
isBilling?: boolean;
|
||||
isEnterprise?: boolean;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user