mirror of
https://github.com/netbirdio/dashboard.git
synced 2026-09-23 00:30:43 -07:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8d57c3445 | ||
|
|
0b892c0056 | ||
|
|
14d9b80029 |
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { Page, test, expect } from "@playwright/test";
|
||||
|
||||
export class AccessControlPage {
|
||||
private readonly accessControlUrl = 'http://localhost:3000/acls'
|
||||
private readonly defaulAccessControl = this.page.getByRole('cell', { name: 'Default' })
|
||||
private readonly deleteButton = this.page.getByRole('button', { name: 'Delete' })
|
||||
private readonly deleteModal = this.page.getByTestId('confirm-delete-modal-title')
|
||||
private readonly confirmButton = this.page.getByRole('button', { name: 'OK' })
|
||||
private readonly addRulesButton = this.page.getByTestId('add-rule-empty-state-button')
|
||||
|
||||
constructor(private readonly page: Page) {}
|
||||
|
||||
async openAccessControlPage() {
|
||||
await test.step('Open Access Control page', async () => {
|
||||
await this.page.goto(this.accessControlUrl);
|
||||
})
|
||||
}
|
||||
|
||||
async assertDefaultAccessCotrolIsCreated() {
|
||||
await test.step('Assert that default cotrol access is created', async () => {
|
||||
await expect(this.defaulAccessControl).toBeVisible();
|
||||
})
|
||||
}
|
||||
|
||||
async pressDeleteButton() {
|
||||
await test.step('Press delete button', async () => {
|
||||
await this.deleteButton.click();
|
||||
})
|
||||
}
|
||||
|
||||
async assertDeleteModalIsVisibile() {
|
||||
await test.step('Assert access control deletion modal is visible', async () => {
|
||||
await expect(this.deleteModal).toBeVisible();
|
||||
})
|
||||
}
|
||||
|
||||
async pressConfirmButton() {
|
||||
await test.step('Press confirm button on access control deletion modal', async () => {
|
||||
await this.confirmButton.click();
|
||||
})
|
||||
}
|
||||
|
||||
async assertDefaultAccessCotrolIsDeleted() {
|
||||
await test.step('Assert default access control should be deleted', async () => {
|
||||
await expect(this.defaulAccessControl).not.toBeVisible();
|
||||
})
|
||||
}
|
||||
|
||||
async assertAddRuleButtonIsVisile() {
|
||||
await test.step('Assert Add Rules button is visible', async () => {
|
||||
await expect(this.addRulesButton).toBeVisible();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default AccessControlPage;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Page, test, expect} from "@playwright/test";
|
||||
|
||||
export class LoginPage {
|
||||
private readonly localUrl = 'http://localhost:3000/'
|
||||
private readonly usernameField = this.page.getByPlaceholder('username@domain')
|
||||
private readonly nextButton = this.page.getByRole('button', { name: 'next' })
|
||||
private readonly passwordField = this.page.getByLabel('Password')
|
||||
private readonly skipButton = this.page.getByRole('button', { name: 'skip' });
|
||||
private readonly netBirdLogo = this.page.getByRole('link', { name: 'logo' })
|
||||
|
||||
constructor(private readonly page: Page) {}
|
||||
|
||||
async doLogin() {
|
||||
await test.step('Login to local enviroment', async () => {
|
||||
await this.page.goto(this.localUrl);
|
||||
await this.usernameField.fill('admin@localhost');
|
||||
await this.pressNextButton();
|
||||
await this.passwordField.fill('testMe123@');
|
||||
await this.pressNextButton();
|
||||
if (await this.skipButton.isVisible({ timeout: 300 })) {
|
||||
await this.skipButton.click();
|
||||
}
|
||||
await expect(this.netBirdLogo).toBeVisible();
|
||||
})
|
||||
}
|
||||
|
||||
async pressNextButton() {
|
||||
await test.step('Press next button', async () => {
|
||||
await this.nextButton.click();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default LoginPage;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page, test, expect } from "@playwright/test";
|
||||
import { Page, test } from "@playwright/test";
|
||||
|
||||
export class PeersPage {
|
||||
private readonly addNewPeerButton = this.page.getByTestId('add-new-peer-button')
|
||||
|
||||
@@ -1,33 +1,22 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import {AddPeerModal} from '../pages/modals/add-peer-modal'
|
||||
import {TopMenu} from '../pages/top-menu';
|
||||
import { test } from '@playwright/test'
|
||||
import {LoginPage} from '../pages/login-page'
|
||||
import {AccessControlPage} from '../pages/access-control-page'
|
||||
|
||||
const URL = 'https://app.netbird.io/'
|
||||
const localUrl = 'http://localhost:3000/'
|
||||
let addPeerModal: AddPeerModal;
|
||||
let topMenu: TopMenu;
|
||||
let loginPage: LoginPage
|
||||
let accessControlPage: AccessControlPage
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
addPeerModal = new AddPeerModal(page);
|
||||
await page.goto(localUrl);
|
||||
await page.getByPlaceholder('username@domain').fill('admin@localhost');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
await page.getByLabel('Password').fill('testMe123@');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
const skipButton = page.getByRole('button', { name: 'skip' });
|
||||
if (await skipButton.isVisible({ timeout: 300 })) {
|
||||
await skipButton.click();
|
||||
}
|
||||
await addPeerModal.assertPeerModalIsVisible();
|
||||
loginPage = new LoginPage(page);
|
||||
await loginPage.doLogin();
|
||||
});
|
||||
|
||||
test('Confirm that new user has Default access', async ({ page }) => {
|
||||
topMenu = new TopMenu(page);
|
||||
await addPeerModal.closeAddPeerModal();
|
||||
await addPeerModal.assertPeerModalIsNotVisible();
|
||||
await topMenu.clickOnAccessControlOnTopMenu();
|
||||
await expect(page.getByRole('cell', { name: 'Default' })).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await expect(page.getByTestId('confirm-delete-modal-title')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
accessControlPage = new AccessControlPage(page);
|
||||
await accessControlPage.openAccessControlPage();
|
||||
await accessControlPage.assertDefaultAccessCotrolIsCreated();
|
||||
await accessControlPage.pressDeleteButton();
|
||||
await accessControlPage.assertDeleteModalIsVisibile();
|
||||
await accessControlPage.pressConfirmButton();
|
||||
await accessControlPage.assertDefaultAccessCotrolIsDeleted();
|
||||
await accessControlPage.assertAddRuleButtonIsVisile();
|
||||
});
|
||||
@@ -1,48 +1,41 @@
|
||||
import { test } from '@playwright/test';
|
||||
import { test } from '@playwright/test'
|
||||
import {AddPeerModal} from '../pages/modals/add-peer-modal'
|
||||
import {PeersPage} from '../pages/peers-page'
|
||||
import {LoginPage} from '../pages/login-page'
|
||||
|
||||
const URL = 'https://app.netbird.io/'
|
||||
const localUrl = 'http://localhost:3000/'
|
||||
let addPeerModal: AddPeerModal;
|
||||
let peersPage: PeersPage;
|
||||
let addPeerModal: AddPeerModal
|
||||
let peersPage: PeersPage
|
||||
let loginPage: LoginPage
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
addPeerModal = new AddPeerModal(page);
|
||||
await page.goto(localUrl);
|
||||
await page.getByPlaceholder('username@domain').fill('admin@localhost');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
await page.getByLabel('Password').fill('testMe123@');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
const skipButton = page.getByRole('button', { name: 'skip' });
|
||||
if (await skipButton.isVisible({ timeout: 300 })) {
|
||||
await skipButton.click();
|
||||
}
|
||||
loginPage = new LoginPage(page);
|
||||
await loginPage.doLogin();
|
||||
await addPeerModal.assertPeerModalIsVisible();
|
||||
});
|
||||
|
||||
test('Test Linux tab on a first access add peer modal / @bc', async function ({ }) {
|
||||
test('Test Linux tab on a first access add peer modal / @bc', async function () {
|
||||
await addPeerModal.openLinuxTab();
|
||||
await addPeerModal.assertLinuxTabHasCorrectText();
|
||||
});
|
||||
|
||||
test('Test Windows tab on a first access add peer modal / @bc', async ({ }) => {
|
||||
test('Test Windows tab on a first access add peer modal / @bc', async () => {
|
||||
await addPeerModal.openWindowsTab();
|
||||
await addPeerModal.assertWindowsDownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
test('Test MacOS tab on a first access add peer modal / @bc', async ({ }) => {
|
||||
test('Test MacOS tab on a first access add peer modal / @bc', async () => {
|
||||
await addPeerModal.openMacTab();
|
||||
await addPeerModal.assertIntelDownloadButtonHasCorrectLink();
|
||||
await addPeerModal.assertM1M2DownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
test('Test Android tab on a first access add peer modal', async ({ }) => {
|
||||
test('Test Android tab on a first access add peer modal', async () => {
|
||||
await addPeerModal.openAndroidTab();
|
||||
await addPeerModal.assertAndroidDownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
test('Test Docker tab on a first access add peer modal', async ({ }) => {
|
||||
test('Test Docker tab on a first access add peer modal', async () => {
|
||||
await addPeerModal.openDockerTab();
|
||||
await addPeerModal.assertDockerDownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
Generated
-33
@@ -12,8 +12,6 @@
|
||||
"@axa-fr/react-oidc": "^5.14.0",
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@heroicons/react": "^1.0.4",
|
||||
"@stripe/react-stripe-js": "^2.1.2",
|
||||
"@stripe/stripe-js": "^2.1.0",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
@@ -3407,24 +3405,6 @@
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stripe/react-stripe-js": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.1.2.tgz",
|
||||
"integrity": "sha512-2JcKRvOdMD698uGrY0cINLHb6XHnY24L+wlWlw2+TbI2aXlQZ9t8Mc+KssFES+EuNgISbrp7fJR3w/13epfiOw==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@stripe/stripe-js": "^1.44.1 || ^2.0.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stripe/stripe-js": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.1.0.tgz",
|
||||
"integrity": "sha512-AdMHWqIq/s3TLmoyuzdb6l21STKDKNm82cjce1VelyQGinVNjVgSEPH5UDtxENEP7OzgMZH8RTphFMi0fMJGLQ=="
|
||||
},
|
||||
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||
@@ -19497,19 +19477,6 @@
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"@stripe/react-stripe-js": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.1.2.tgz",
|
||||
"integrity": "sha512-2JcKRvOdMD698uGrY0cINLHb6XHnY24L+wlWlw2+TbI2aXlQZ9t8Mc+KssFES+EuNgISbrp7fJR3w/13epfiOw==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@stripe/stripe-js": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.1.0.tgz",
|
||||
"integrity": "sha512-AdMHWqIq/s3TLmoyuzdb6l21STKDKNm82cjce1VelyQGinVNjVgSEPH5UDtxENEP7OzgMZH8RTphFMi0fMJGLQ=="
|
||||
},
|
||||
"@surma/rollup-plugin-off-main-thread": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||
|
||||
+2
-4
@@ -7,8 +7,6 @@
|
||||
"@axa-fr/react-oidc": "^5.14.0",
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@heroicons/react": "^1.0.4",
|
||||
"@stripe/react-stripe-js": "^2.1.2",
|
||||
"@stripe/stripe-js": "^2.1.0",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
@@ -81,7 +79,7 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.36.2",
|
||||
"@types/react-syntax-highlighter": "^15.5.3"
|
||||
"@types/react-syntax-highlighter": "^15.5.3",
|
||||
"@playwright/test": "^1.36.2"
|
||||
}
|
||||
}
|
||||
@@ -39,15 +39,15 @@ export default defineConfig({
|
||||
use: { channel: 'chrome', },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { browserName: 'firefox', },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { browserName: 'webkit', },
|
||||
},
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: { browserName: 'firefox', },
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: { browserName: 'webkit', },
|
||||
// },
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
|
||||
Whitespace-only changes.
@@ -8,6 +8,7 @@ export interface User {
|
||||
is_current?: boolean;
|
||||
is_service_user?: boolean;
|
||||
is_blocked?: boolean;
|
||||
last_login?: string;
|
||||
}
|
||||
|
||||
export interface FormUser extends User {
|
||||
|
||||
+3
-1
@@ -100,7 +100,7 @@ export const timeAgo = (dateParam) => {
|
||||
const isToday = today.toDateString() === date.toDateString();
|
||||
const isYesterday = yesterday.toDateString() === date.toDateString();
|
||||
const isThisYear = today.getFullYear() === date.getFullYear();
|
||||
|
||||
const never = date.getFullYear() === 1;
|
||||
|
||||
if (seconds < -1) {
|
||||
return getFormattedDate(date, false, true);
|
||||
@@ -118,6 +118,8 @@ export const timeAgo = (dateParam) => {
|
||||
return getFormattedDate(date, 'yesterday'); // Yesterday at 10:20
|
||||
} else if (isThisYear) {
|
||||
return getFormattedDate(date, false, true); // 10. January at 10:20
|
||||
} else if (never) {
|
||||
return 'never';
|
||||
}
|
||||
|
||||
return getFormattedDate(date); // 10. January 2017. at 10:20
|
||||
|
||||
@@ -666,6 +666,7 @@ export const AccessControl = () => {
|
||||
<Row justify="end">
|
||||
<Col>
|
||||
<Button
|
||||
data-testid="add-rule-main-button"
|
||||
type="primary"
|
||||
disabled={savedPolicy.loading}
|
||||
onClick={onClickAddNewPolicy}
|
||||
@@ -719,6 +720,7 @@ export const AccessControl = () => {
|
||||
</a>
|
||||
</Paragraph>
|
||||
<Button
|
||||
data-testid="add-rule-empty-state-button"
|
||||
size={"middle"}
|
||||
type="primary"
|
||||
onClick={() => onClickAddNewPolicy()}
|
||||
|
||||
@@ -170,6 +170,21 @@ export const Activity = () => {
|
||||
let body = <></>;
|
||||
const user = users?.find((u) => u.id === event.initiator_id);
|
||||
switch (event.activity_code) {
|
||||
case "peer.login.expire":
|
||||
body = (
|
||||
<span
|
||||
style={{
|
||||
height: "auto",
|
||||
whiteSpace: "normal",
|
||||
textAlign: "left",
|
||||
}}
|
||||
>
|
||||
<Row>
|
||||
<Text type="secondary">System</Text>
|
||||
</Row>
|
||||
</span>
|
||||
);
|
||||
break;
|
||||
case "setupkey.peer.add":
|
||||
const key = setupKeys?.find((k) => k.id === event.initiator_id);
|
||||
if (key) {
|
||||
@@ -255,6 +270,7 @@ export const Activity = () => {
|
||||
switch (event.activity_code) {
|
||||
case "account.create":
|
||||
case "user.join":
|
||||
case "dashboard.login":
|
||||
return "-";
|
||||
case "rule.add":
|
||||
case "rule.delete":
|
||||
@@ -290,6 +306,8 @@ export const Activity = () => {
|
||||
case "peer.rename":
|
||||
case "peer.login.expiration.disable":
|
||||
case "peer.login.expiration.enable":
|
||||
case "user.peer.login":
|
||||
case "peer.login.expire":
|
||||
return renderMultiRowSpan(event.meta.fqdn, event.meta.ip);
|
||||
case "route.add":
|
||||
case "route.delete":
|
||||
|
||||
+5
-5
@@ -633,16 +633,16 @@ export const Peers = () => {
|
||||
<Container style={{ paddingTop: "40px" }}>
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Title className="page-heading">Peers</Title>
|
||||
<Title className="page-heading">{isAdmin ? "Peers" : "My peers"}</Title>
|
||||
{peers.length ? (
|
||||
<Paragraph style={{ marginTop: "5px" }}>
|
||||
A list of all machines and devices connected to your private
|
||||
network. Use this view to manage peers
|
||||
{isAdmin ? "A list of all machines and devices connected to your private network. Use this view to manage peers" :
|
||||
"A list of all your machines and devices that you connected to NetBird."}
|
||||
</Paragraph>
|
||||
) : (
|
||||
<Paragraph style={{ marginTop: "5px" }} type={"secondary"}>
|
||||
A list of all machines and devices connected to your private
|
||||
network. Use this view to manage peers
|
||||
{isAdmin ? "A list of all machines and devices connected to your private network. Use this view to manage peers" :
|
||||
"A list of all your machines and devices that you connected to NetBird."}
|
||||
</Paragraph>
|
||||
)}
|
||||
|
||||
|
||||
+35
-26
@@ -31,7 +31,7 @@ import { useGetTokenSilently } from "../utils/token";
|
||||
import { actions as groupActions } from "../store/group";
|
||||
import { Group } from "../store/group/types";
|
||||
import { TooltipPlacement } from "antd/es/tooltip";
|
||||
import { capitalize, isLocalDev, isNetBirdHosted } from "../utils/common";
|
||||
import {capitalize, isLocalDev, isNetBirdHosted, timeAgo} from "../utils/common";
|
||||
import { usePageSizeHelpers } from "../utils/pageSize";
|
||||
import AddServiceUserPopup from "../components/popups/AddServiceUserPopup";
|
||||
import InviteUserPopup from "../components/popups/InviteUserPopup";
|
||||
@@ -499,45 +499,54 @@ export const RegularUsers = () => {
|
||||
defaultSortOrder="ascend"
|
||||
render={(text, record, index) => {
|
||||
const btn = (
|
||||
<Button
|
||||
type="text"
|
||||
onClick={() =>
|
||||
handleEditUser(record as UserDataTable)
|
||||
}
|
||||
className="tooltip-label"
|
||||
>
|
||||
<Text className="font-500">
|
||||
{text && text.trim() !== ""
|
||||
? text
|
||||
: (record as User).id}
|
||||
</Text>
|
||||
</Button>
|
||||
<Button
|
||||
type="text"
|
||||
onClick={() =>
|
||||
handleEditUser(record as UserDataTable)
|
||||
}
|
||||
className="tooltip-label"
|
||||
>
|
||||
<Text className="font-500">
|
||||
{text && text.trim() !== ""
|
||||
? text
|
||||
: (record as User).id}
|
||||
</Text>
|
||||
</Button>
|
||||
);
|
||||
|
||||
if ((record as User).is_current) {
|
||||
return (
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="blue">me</Tag>
|
||||
</div>
|
||||
<>
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="blue">me</Tag>
|
||||
</div>
|
||||
<Text type={"secondary"} style={{paddingLeft: "15px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if ((record as User).status === "invited") {
|
||||
return (
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="gold">invited</Tag>
|
||||
</div>
|
||||
<>
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="gold">invited</Tag>
|
||||
</div>
|
||||
<Text type={"secondary"} style={{paddingLeft: "15px", paddingTop: "0px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if ((record as User).status === "blocked") {
|
||||
return (
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="red">blocked</Tag>
|
||||
</div>
|
||||
<>
|
||||
<div>
|
||||
{btn}
|
||||
<Tag color="red">blocked</Tag>
|
||||
</div>
|
||||
<Text type={"secondary"} style={{paddingLeft: "15px"}}>Last login: {String(timeAgo((record as User).last_login))}</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+1
-69
@@ -33,7 +33,6 @@ import ExpiresInInput, {
|
||||
expiresInToSeconds,
|
||||
secondsToExpiresIn,
|
||||
} from "./ExpiresInInput";
|
||||
// import CheckoutPage from "../components/CheckoutForm";
|
||||
import Column from "antd/lib/table/Column";
|
||||
import TableSpin from "../components/Spin";
|
||||
import { checkExpiresIn } from "../utils/common";
|
||||
@@ -56,8 +55,6 @@ const { Title, Paragraph, Text } = Typography;
|
||||
const styleNotification = { marginTop: 85 };
|
||||
|
||||
export const Settings = () => {
|
||||
const [paymentCompleted, setPaymentCompleted] = useState(false);
|
||||
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
const { pageSize, onChangePageSize, pageSizeOptions } = usePageSizeHelpers(
|
||||
@@ -574,11 +571,7 @@ export const Settings = () => {
|
||||
"System settings",
|
||||
"sub2",
|
||||
<SettingOutlined />,
|
||||
[
|
||||
getItem("Authentication", "auth"),
|
||||
getItem("Groups", "groups"),
|
||||
getItem("Billing", "billing"),
|
||||
],
|
||||
[getItem("Authentication", "auth"), getItem("Groups", "groups")],
|
||||
"group"
|
||||
),
|
||||
];
|
||||
@@ -1129,67 +1122,6 @@ export const Settings = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{billingClicked && (
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Space
|
||||
direction="vertical"
|
||||
size="large"
|
||||
style={{ display: "flex" }}
|
||||
>
|
||||
<Row style={{ width: "100%" }}>
|
||||
<Col span={24}>
|
||||
<Card loading={loading}>
|
||||
<div
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontWeight: "500",
|
||||
fontSize: "18px",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
Billing - Free plan
|
||||
</div>
|
||||
<Row>
|
||||
<Col span={12} style={{ marginBottom: "20px" }}>
|
||||
<Alert
|
||||
description="The Free plan allows you to add up to 5 users and 100 peers."
|
||||
type="info"
|
||||
action={
|
||||
<Space>
|
||||
<Button size="small" type="primary">
|
||||
Upgrade
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
<Space size={30} wrap></Space>
|
||||
<Col span={24}>
|
||||
<Progress
|
||||
strokeColor={"#1890FF"}
|
||||
percent={60}
|
||||
size={[200, 20]}
|
||||
format={(percent) => `${users.length}/5 users`}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Progress
|
||||
strokeColor={"#1890FF"}
|
||||
percent={10}
|
||||
size={[500, 20]}
|
||||
format={(percent) => `10/100 peers`}
|
||||
/>
|
||||
</Col>
|
||||
{/* <CheckoutPage /> */}
|
||||
</Row>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
Reference in new issue
Block a user