Compare commits

..
7 Commits
26 changed files with 1256 additions and 655 deletions

No files matched your search

+740 -437
View File
File diff suppressed because it is too large. Load diff
+4 -2
View File
@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/icons": "^4.8.0",
"@axa-fr/react-oidc": "^5.14.0",
"@headlessui/react": "^1.5.0",
"@heroicons/react": "^1.0.4",
@@ -18,7 +18,7 @@
"@types/react-redux": "^7.1.24",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.25",
"antd": "^4.20.6",
"antd": "^5.3.1",
"autoprefixer": "^10.4.4",
"axios": "^0.27.2",
"cidr-regex": "^3.1.1",
@@ -27,11 +27,13 @@
"highlight.js": "^11.2.0",
"history": "^5.0.1",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"postcss": "^8.4.12",
"prop-types": "^15.7.2",
"punycode": "^2.1.1",
"rc-overflow": "^1.2.8",
"react": "^18.2.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.1.0",
"react-hotjar": "^5.1.0",
"react-redux": "^8.0.2",
+52 -43
View File
@@ -4,7 +4,7 @@ import {apiClient, store} from "./store";
import {hotjar} from 'react-hotjar';
import {getConfig} from "./config";
import Banner from "./components/Banner";
import {Col, Layout, Row} from "antd";
import {Col, ConfigProvider, Layout, Row} from "antd";
import {Container} from "./components/Container";
import Navbar from "./components/Navbar";
import {Redirect, Route, Switch} from "react-router-dom";
@@ -24,7 +24,6 @@ import Activity from "./views/Activity";
import Settings from "./views/Settings";
const {Header, Content} = Layout;
function App() {
@@ -58,7 +57,7 @@ function App() {
run.current = true
apiClient.request<User[]>('GET', `/api/users`, {getAccessTokenSilently: getAccessTokenSilently})
.then(() => {
setShow(true)
setShow(true)
})
.catch(e => {
setShow(true)
@@ -70,51 +69,61 @@ function App() {
return (
<>
<ConfigProvider
theme={{
token: {
borderRadius: 4,
colorPrimary: "#1890ff",
fontFamily: "Arial"
},
}}
>
<Provider store={store}>
{!show && <SecureLoading padding="3em" width={50} height={50}/>}
{show &&
<Layout>
<Banner/>
<Header className="header" style={{
display: "flex",
flexDirection: "column",
justifyContent: "space-around",
alignContent: "center"
}}>
<Row justify="space-around" align="middle">
<Col span={24}>
<Container>
<Navbar/>
</Container>
</Col>
</Row>
</Header>
<Content style={{minHeight: "100vh"}}>
<Switch>
<Route
exact
path="/"
render={() => {
return (
<Redirect to="/peers"/>
)
}}
/>
<Route path='/peers' exact component={withOidcSecure(Peers)}/>
<Route path="/add-peer" component={withOidcSecure(AddPeer)}/>
<Route path="/setup-keys" component={withOidcSecure(SetupKeys)}/>
<Route path="/acls" component={withOidcSecure(AccessControl)}/>
<Route path="/routes" component={withOidcSecure(Routes)}/>
<Route path="/users" component={withOidcSecure(Users)}/>
<Route path="/dns" component={withOidcSecure(DNS)}/>
<Route path="/activity" component={withOidcSecure(Activity)}/>
<Route path="/settings" component={withOidcSecure(Settings)}/>
</Switch>
</Content>
<FooterComponent/>
</Layout>
<Layout>
<Banner/>
<Header className="header" style={{
display: "flex",
flexDirection: "column",
justifyContent: "space-around",
alignContent: "center"
}}>
<Row justify="space-around" align="middle">
<Col span={24}>
<Container>
<Navbar/>
</Container>
</Col>
</Row>
</Header>
<Content style={{minHeight: "100vh"}}>
<Switch>
<Route
exact
path="/"
render={() => {
return (
<Redirect to="/peers"/>
)
}}
/>
<Route path='/peers' exact component={withOidcSecure(Peers)}/>
<Route path="/setup-keys" component={withOidcSecure(SetupKeys)}/>
<Route path="/acls" component={withOidcSecure(AccessControl)}/>
<Route path="/routes" component={withOidcSecure(Routes)}/>
<Route path="/users" component={withOidcSecure(Users)}/>
<Route path="/dns" component={withOidcSecure(DNS)}/>
<Route path="/activity" component={withOidcSecure(Activity)}/>
<Route path="/settings" component={withOidcSecure(Settings)}/>
</Switch>
</Content>
<FooterComponent/>
</Layout>
}
</Provider>
</ConfigProvider>
</>
)
}
+1 -3
View File
@@ -408,9 +408,7 @@ const AccessControlNew = () => {
<Col span={24}>
<Divider></Divider>
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank"
href="https://docs.netbird.io/docs/overview/acls"
style={{color: 'rgb(07, 114, 128)'}}>Learn
more about access controls</Button>
href="https://docs.netbird.io/docs/overview/acls">Learn more about access controls</Button>
</Col>
</Row>
</Form>
+1 -3
View File
@@ -604,9 +604,7 @@ const NameServerGroupUpdate = () => {
<Col span={24}>
<Divider></Divider>
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank"
href="https://netbird.io/docs/how-to-guides/nameservers"
style={{color: 'rgb(07, 114, 128)'}}>Learn
more about nameservers</Button>
href="https://netbird.io/docs/how-to-guides/nameservers">Learn more about nameservers</Button>
</Col>
</Row>
</Form>) :
-1
View File
@@ -35,7 +35,6 @@ const Navbar = () => {
const items = [
{label: (<Link to="/peers">Peers</Link>), key: '/peers'},
{label: (<Link to="/add-peer">Add Peer</Link>), key: '/add-peer'},
{label: (<Link to="/setup-keys">Setup Keys</Link>), key: '/setup-keys'},
{label: (<Link to="/acls">Access Control</Link>), key: '/acls'},
{label: (<Link to="/routes">Network Routes</Link>), key: '/routes'},
+1 -3
View File
@@ -453,9 +453,7 @@ const RouteUpdate = () => {
<Col span={24}>
<Divider></Divider>
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank"
href="https://netbird.io/docs/how-to-guides/network-routes"
style={{color: 'rgb(07, 114, 128)'}}>Learn
more about network routes</Button>
href="https://netbird.io/docs/how-to-guides/network-routes">Learn more about network routes</Button>
</Col>
</Row>
</Form>
+10 -8
View File
@@ -11,7 +11,7 @@ import {
Form,
Input,
InputNumber,
List,
List, Modal,
Radio,
Row,
Select,
@@ -29,6 +29,7 @@ import {CustomTagProps} from "rc-select/lib/BaseSelect";
import {Group} from "../store/group/types";
import {useGetAccessTokenSilently} from "../utils/token";
import ExpiresInInput, {expiresInToSeconds, ExpiresInValue} from "../views/ExpiresInInput";
import moment from "moment";
const {Option} = Select;
@@ -41,7 +42,8 @@ const customExpiresFormat: DatePickerProps['format'] = value => {
}
const customLastUsedFormat: DatePickerProps['format'] = value => {
if (value.toString().startsWith("0001")) {
if (value.year() == 1) {
// 1st of Jan 0001
return "never"
}
let ago = timeAgo(value.toString())
@@ -93,7 +95,9 @@ const SetupKeyNew = () => {
const fSetupKey = {
...setupKey,
autoGroupNames: setupKey.auto_groups ? formKeyGroups : [],
expiresInFormatted: ExpiresInDefault
expiresInFormatted: ExpiresInDefault,
exp: moment(setupKey.expires),
last: moment(setupKey.last_used)
} as FormSetupKey
setFormSetupKey(fSetupKey)
form.setFieldsValue(fSetupKey)
@@ -352,7 +356,7 @@ const SetupKeyNew = () => {
{setupKey.id && formSetupKey.name &&
<Col span={12}>
<Form.Item
name="expires"
name="exp"
label="Expires"
tooltip="The expiration date of the key"
>
@@ -365,7 +369,7 @@ const SetupKeyNew = () => {
{setupKey.id && formSetupKey.name &&
<Col span={12}>
<Form.Item
name="last_used"
name="last"
label="Last Used"
tooltip="The last time the key was used"
>
@@ -470,9 +474,7 @@ const SetupKeyNew = () => {
<Col span={24}>
<Divider></Divider>
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank"
href="https://netbird.io/docs/overview/setup-keys"
style={{color: 'rgb(07, 114, 128)'}}>Learn
more about setup keys</Button>
href="https://netbird.io/docs/overview/setup-keys">Learn more about setup keys</Button>
</Col>
</Row>
</Form>
+100
View File
@@ -0,0 +1,100 @@
import React, {useState} from 'react';
import {Tabs, TabsProps} from "antd";
import Icon, {AndroidFilled, AppleFilled, WindowsFilled} from "@ant-design/icons";
import {ReactComponent as LinuxSVG} from "../icons/terminal_icon.svg";
import UbuntuTab from "./UbuntuTab";
import {ReactComponent as DockerSVG} from "../icons/docker_icon.svg";
import Paragraph from "antd/lib/typography/Paragraph";
import WindowsTab from "./WindowsTab";
import MacTab from "./MacTab";
import Link from "antd/lib/typography/Link";
import DockerTab from "./DockerTab";
type Props = {
greeting?: string;
headline: string;
};
const detectOSTab = () => {
let os = 1;
if (navigator.userAgent.indexOf("Win") !== -1) os = 2;
if (navigator.userAgent.indexOf("Mac") !== -1) os = 3;
if (navigator.userAgent.indexOf("X11") !== -1) os = 1;
if (navigator.userAgent.indexOf("Linux") !== -1) os = 1
return os
}
export const AddPeerPopup: React.FC<Props> = ({
greeting,
headline,
}) => {
const [openTab, setOpenTab] = useState(detectOSTab);
const [width, setWidth] = useState<number>(window.innerWidth);
const isMobile = width <= 768;
const items: TabsProps['items'] = [
{
key: "1",
label: <span><Icon component={LinuxSVG}/>Ubuntu</span>,
children: <UbuntuTab/>,
},
{
key: "2",
label: <span><WindowsFilled/>Windows</span>,
children: <WindowsTab/>,
},
{
key: "3",
label: <span><AppleFilled/>macOS</span>,
children: <MacTab/>,
},
/*{
key: "4",
label: <span><AndroidFilled/>Android</span>,
children: <></>,
},*/
{
key: "5",
label: <span><Icon component={DockerSVG}/>Docker</span>,
children: <DockerTab/>,
}
];
return <>
{greeting && <Paragraph
style={{textAlign: "center", whiteSpace: "pre-line", fontSize: "2em", marginBottom: -10}}>
{greeting}
</Paragraph>}
<Paragraph
style={{textAlign: "center", whiteSpace: "pre-line", fontSize: "2em"}}>
{headline}
</Paragraph>
<Paragraph type={"secondary"}
style={{
marginTop: "-15px",
textAlign: "center",
whiteSpace: "pre-line",
}}>
To get started install NetBird and log in using your {"\n"} email account.
</Paragraph>
<Tabs centered={!isMobile}
defaultActiveKey={openTab.toString()} tabPosition="top" animated={{inkBar: true, tabPane: false}}
items={items}/>
<Paragraph type={"secondary"}
style={{
marginTop: "15px",
}}>
After that you should be connected. Add more devices to your network or manage your existing devices in the
admin panel.
If you have further questions check out our {<Link target="_blank"
href={"https://netbird.io/docs/getting-started/installation"}>installation
guide</Link>}
</Paragraph>
</>
}
export default AddPeerPopup
+63
View File
@@ -0,0 +1,63 @@
import React, {useState} from 'react';
import {StepCommand} from "./types"
import {formatDockerCommand, formatNetBirdUP} from "./common"
import SyntaxHighlighter from "react-syntax-highlighter";
import TabSteps from "./TabSteps";
import {Button, Typography} from "antd";
import Link from "antd/lib/typography/Link";
const {Title, Paragraph, Text} = Typography;
export const DockerTab = () => {
const [steps, setSteps] = useState([
{
key: 1,
title: 'Install Docker',
commands: (
<Button style={{marginTop: "5px"}} type="primary" href="https://docs.docker.com/engine/install/" target="_blank">Official Docker website</Button>
),
copied: false,
showCopyButton: false
} as StepCommand,
{
key: 2,
title: 'Run NetBird container',
commands: formatDockerCommand(),
copied: false,
showCopyButton: false
} as StepCommand,
{
key: 3,
title: "Read docs",
commands: (
<Link href="https://netbird.io/docs/getting-started/installation#running-netbird-in-docker" target="_blank">Running NetBird in Docker</Link>
),
copied: false,
showCopyButton: false
} as StepCommand
])
return (
<div style={{marginTop: 10}}>
{/*<Text style={{fontWeight: "bold"}}>
Run in Docker
</Text>
<div style={{fontSize: ".85em", marginTop: 5, marginBottom: 25}}>
<SyntaxHighlighter language="bash">
{formatDockerCommand()}
</SyntaxHighlighter>
</div>*/}
<Text style={{fontWeight: "bold"}}>
Install on Ubuntu
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</div>
)
}
export default DockerTab
+61 -15
View File
@@ -1,18 +1,49 @@
import React, {useState} from 'react';
import { Button } from "antd";
import {Button, Typography} from "antd";
import TabSteps from "./TabSteps";
import { StepCommand } from "./types"
import { formatNetBirdUP } from "./common"
import {StepCommand} from "./types"
import {formatNetBirdUP} from "./common"
import {Collapse} from "antd";
const { Panel } = Collapse;
const {Text} = Typography;
export const LinuxTab = () => {
const [quickSteps, setQuickSteps] = useState([
{
key: 1,
title: 'Download and run installer:',
commands: (
<Button style={{marginTop: "5px"}} type="primary" href="https://pkgs.netbird.io/windows/x64"
target="_blank">Download NetBird</Button>
),
copied: false
} as StepCommand,
{
key: 2,
title: 'Click on "Connect" from the NetBird icon in your system tray',
commands: '',
copied: false,
showCopyButton: false
},
{
key: 3,
title: 'Sign up using your email address',
commands: '',
copied: false,
showCopyButton: false
}
])
const [steps, setSteps] = useState([
{
key: 1,
title: 'Download and install Brew (package manager)',
title: 'Download and install Homebrew',
commands: (
<Button type="primary" href="https://brew.sh/" target="_blank">Download Brew</Button>
<Button style={{marginTop: "5px"}} type="primary" href="https://brew.sh/" target="_blank">Download
Brew</Button>
),
copied: false
} as StepCommand,
@@ -44,20 +75,35 @@ export const LinuxTab = () => {
commands: formatNetBirdUP(),
copied: false,
showCopyButton: true
} as StepCommand,
{
key: 5,
title: 'Get your IP address:',
commands: [
`sudo ifconfig utun100`
].join('\n'),
copied: false,
showCopyButton: true
} as StepCommand
])
return (
<TabSteps stepsItems={steps}/>
/*<div style={{marginTop: 10}}>
<Text style={{fontWeight: "bold"}}>
Install on macOS
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={quickSteps}/>
</div>
<Collapse style={{marginLeft: -15}} bordered={false}>
<Panel header={<Text style={{fontWeight: "bold"}}>
Or install manually with Homebrew
</Text>} key="1">
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</Panel>
</Collapse>
</div>*/
<div style={{marginTop: 10}}>
<Text style={{fontWeight: "bold"}}>
Install on macOS with Homebrew
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</div>
)
}
+7 -20
View File
@@ -2,16 +2,16 @@ import "highlight.js/styles/mono-blue.css";
import "highlight.js/lib/languages/bash";
import { StepCommand } from './types'
import SyntaxHighlighter from 'react-syntax-highlighter';
import { monoBlue } from 'react-syntax-highlighter/dist/esm/styles/hljs';
import {
Typography,
Space,
Steps, Button
Steps, Button, Popover, StepsProps
} from "antd";
import {copyToClipboard} from "../../utils/common";
import {CheckOutlined, CopyOutlined} from "@ant-design/icons";
import React, {useEffect, useState} from "react";
const { Step } = Steps;
const {Text} = Typography;
type Props = {
stepsItems: Array<StepCommand>
@@ -36,35 +36,22 @@ const TabSteps:React.FC<Props> = ({stepsItems}) => {
}, 2000)
}
}
return (
<Steps direction="vertical" current={0}>
<Steps direction="vertical" size={"small"}>
{steps.map(c =>
<Step
status={"process"}
key={c.key}
title={c.title}
title={<Text>{c.title}</Text>}
description={
<Space className="nb-code" direction="vertical" size="small" style={{display: "flex"}}>
<Space className="nb-code" direction="vertical" size="small" style={{display: "flex", fontSize: ".85em"}}>
{ (c.commands && (typeof c.commands === 'string')) ? (
<SyntaxHighlighter language="bash" style={monoBlue}>
<SyntaxHighlighter language="bash">
{c.commands}
</SyntaxHighlighter>
) : (
c.commands
)}
{ c.showCopyButton &&
<>
{ !c.copied ? (
<Button type="text" size="large" className="btn-copy-code" icon={<CopyOutlined/>}
style={{color: "rgb(107, 114, 128)"}}
onClick={() => onCopyClick(c.key, c.commands, true)}/>
): (
<Button type="text" size="large" className="btn-copy-code" icon={<CheckOutlined/>}
style={{color: "green"}}/>
)}
</>
}
</Space>
}
/>
+34 -36
View File
@@ -1,31 +1,29 @@
import React, { useState } from 'react';
import { Button } from "antd";
import React, {useState} from 'react';
import {StepCommand} from "./types"
import {formatNetBirdUP} from "./common"
import SyntaxHighlighter from "react-syntax-highlighter";
import TabSteps from "./TabSteps";
import { StepCommand } from "./types"
import { getConfig } from "../../config";
import Paragraph from 'antd/lib/skeleton/Paragraph';
import { formatNetBirdUP } from "./common"
import {Typography} from "antd";
const {Title, Paragraph, Text} = Typography;
export const UbuntuTab = () => {
const [steps, setSteps] = useState([
{
key: 1,
title: 'Add repository:',
title: 'Add repository',
commands: [
`sudo apt install ca-certificates curl gnupg -y`,
`curl -L https://pkgs.wiretrustee.com/debian/public.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/wiretrustee.gpg`,
`echo 'deb https://pkgs.wiretrustee.com/debian stable main' | sudo tee /etc/apt/sources.list.d/wiretrustee.list`
].join('\n'),
copied: false,
showCopyButton: true
showCopyButton: false
} as StepCommand,
{
key: 2,
title: 'Install NetBird:',
title: 'Install NetBird',
commands: [
`sudo apt-get update`,
`# for CLI only`,
@@ -34,39 +32,39 @@ export const UbuntuTab = () => {
`sudo apt-get install netbird-ui`
].join('\n'),
copied: false,
showCopyButton: true
showCopyButton: false
} as StepCommand,
{
key: 3,
title: 'Run NetBird and log in the browser:',
title: 'Run NetBird and log in the browser',
commands: formatNetBirdUP(),
copied: false,
showCopyButton: true
} as StepCommand,
{
key: 4,
title: 'Get your IP address:',
commands: [
`ip addr show wt0`
].join('\n'),
copied: false,
showCopyButton: true
} as StepCommand,
showCopyButton: false
} as StepCommand
])
/*const clickTest = () => {
steps.push({
key: steps.length+1,
title: `Test ${steps.length+1}`,
commands: [`hi lorena!`].join('\n'),
copied: false
})
console.log(steps)
setSteps([...steps])
}*/
return (
<TabSteps stepsItems={steps} />
<div style={{marginTop: 10}}>
{/*<Text style={{fontWeight: "bold"}}>
Install with one command
</Text>
<div style={{fontSize: ".85em", marginTop: 5, marginBottom: 25}}>
<SyntaxHighlighter language="bash">
curl -fsSL https://netbird.io/install.sh | sh
</SyntaxHighlighter>
</div>*/}
{/*<Text style={{fontWeight: "bold"}}>*/}
{/* Or install manually*/}
{/*</Text>*/}
<Text style={{fontWeight: "bold"}}>
Install on Ubuntu
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</div>
)
}
+14 -5
View File
@@ -1,8 +1,9 @@
import React, {useState} from 'react';
import { Button } from "antd";
import {Button, Typography} from "antd";
import TabSteps from "./TabSteps";
import { StepCommand } from "./types"
const {Text} = Typography;
export const WindowsTab = () => {
@@ -11,20 +12,20 @@ export const WindowsTab = () => {
key: 1,
title: 'Download and run Windows installer:',
commands: (
<Button type="primary" href="https://pkgs.netbird.io/windows/x64" target="_blank">Download NetBird</Button>
<Button style={{marginTop: "5px"}} type="primary" href="https://pkgs.netbird.io/windows/x64" target="_blank">Download NetBird</Button>
),
copied: false
} as StepCommand,
{
key: 2,
title: 'Click on "Connect" from the NetBird icon in your system tray.',
title: 'Click on "Connect" from the NetBird icon in your system tray',
commands: '',
copied: false,
showCopyButton: false
},
{
key: 3,
title: 'Log in your browser.\n',
title: 'Sign up using your email address',
commands: '',
copied: false,
showCopyButton: false
@@ -32,7 +33,15 @@ export const WindowsTab = () => {
])
return (
<TabSteps stepsItems={steps}/>
<div style={{marginTop: 10}}>
<Text style={{fontWeight: "bold"}}>
Install on Windows
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</div>
)
}
+14 -2
View File
@@ -3,11 +3,23 @@ const { grpcApiOrigin } = getConfig();
export const formatNetBirdUP = () => {
let cmd = "sudo netbird up"
let cmd = "netbird up"
if (grpcApiOrigin) {
cmd = "sudo netbird up --management-url " + grpcApiOrigin
cmd = "netbird up --management-url " + grpcApiOrigin
}
return [
cmd
].join('\n')
}
export const formatDockerCommand = () => {
let cmd = ["docker run --rm -d",
" --cap-add=NET_ADMIN",
" -e NB_SETUP_KEY=SETUP_KEY",
" -v netbird-client:/etc/netbird"]
if (grpcApiOrigin) {
cmd.push(" -e NB_MANAGEMENT_URL="+grpcApiOrigin)
}
cmd.push(" netbirdio/netbird:latest")
return cmd.join(' \\\n')
}
+1 -1
View File
@@ -2,7 +2,7 @@ import * as React from "react";
export interface StepCommand {
key: number | string,
title: string,
title: React.ReactNode | string | null,
commands: React.ReactNode | string | null,
copied?: boolean,
showCopyButton?: boolean
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" ?><svg data-name="Layer 1" id="Layer_1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M507,211.16c-1.42-1.19-14.25-10.94-41.79-10.94a132.55,132.55,0,0,0-21.61,1.9c-5.22-36.4-35.38-54-36.57-55l-7.36-4.28-4.75,6.9a101.65,101.65,0,0,0-13.06,30.45c-5,20.7-1.9,40.2,8.55,56.85-12.59,7.14-33,8.8-37.28,9H15.94A15.93,15.93,0,0,0,0,262.07,241.25,241.25,0,0,0,14.75,348.9C26.39,379.35,43.72,402,66,415.74,91.22,431.2,132.3,440,178.6,440a344.23,344.23,0,0,0,62.45-5.71,257.44,257.44,0,0,0,81.69-29.73,223.55,223.55,0,0,0,55.57-45.67c26.83-30.21,42.74-64,54.38-94h4.75c29.21,0,47.26-11.66,57.23-21.65a63.31,63.31,0,0,0,15.2-22.36l2.14-6.18Z"/><path d="M47.29,236.37H92.4a4,4,0,0,0,4-4h0V191.89a4,4,0,0,0-4-4H47.29a4,4,0,0,0-4,4h0v40.44a4.16,4.16,0,0,0,4,4h0"/><path d="M109.5,236.37h45.12a4,4,0,0,0,4-4h0V191.89a4,4,0,0,0-4-4H109.5a4,4,0,0,0-4,4v40.44a4.16,4.16,0,0,0,4,4"/><path d="M172.9,236.37H218a4,4,0,0,0,4-4h0V191.89a4,4,0,0,0-4-4H172.9a4,4,0,0,0-4,4h0v40.44a3.87,3.87,0,0,0,4,4h0"/><path d="M235.36,236.37h45.12a4,4,0,0,0,4-4V191.89a4,4,0,0,0-4-4H235.36a4,4,0,0,0-4,4h0v40.44a4,4,0,0,0,4,4h0"/><path d="M109.5,178.57h45.12a4.16,4.16,0,0,0,4-4V134.09a4,4,0,0,0-4-4H109.5a4,4,0,0,0-4,4v40.44a4.34,4.34,0,0,0,4,4"/><path d="M172.9,178.57H218a4.16,4.16,0,0,0,4-4V134.09a4,4,0,0,0-4-4H172.9a4,4,0,0,0-4,4h0v40.44a4,4,0,0,0,4,4"/><path d="M235.36,178.57h45.12a4.16,4.16,0,0,0,4-4V134.09a4.16,4.16,0,0,0-4-4H235.36a4,4,0,0,0-4,4h0v40.44a4.16,4.16,0,0,0,4,4"/><path d="M235.36,120.53h45.12a4,4,0,0,0,4-4V76a4.16,4.16,0,0,0-4-4H235.36a4,4,0,0,0-4,4h0v40.44a4.17,4.17,0,0,0,4,4"/><path d="M298.28,236.37H343.4a4,4,0,0,0,4-4V191.89a4,4,0,0,0-4-4H298.28a4,4,0,0,0-4,4h0v40.44a4.16,4.16,0,0,0,4,4"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" ?><svg height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><title/><path d="M432,32H80A64.07,64.07,0,0,0,16,96V416a64.07,64.07,0,0,0,64,64H432a64.07,64.07,0,0,0,64-64V96A64.07,64.07,0,0,0,432,32ZM96,256a16,16,0,0,1-10-28.49L150.39,176,86,124.49a16,16,0,1,1,20-25l80,64a16,16,0,0,1,0,25l-80,64A16,16,0,0,1,96,256Zm160,0H192a16,16,0,0,1,0-32h64a16,16,0,0,1,0,32Z"/></svg>

After

Width:  |  Height:  |  Size: 419 B

+23 -19
View File
@@ -1,8 +1,4 @@
@import '~antd/dist/antd.css';
/*@tailwind base;*/
/*@tailwind components;*/
/*@tailwind utilities;*/
@import 'antd/dist/reset.css';
body {
font-size: 16px;
@@ -92,20 +88,6 @@ body {
align-self: center;
}
.ant-steps-item-tail::after {
background-color: #1890ff !important;
}
.ant-steps-item-icon {
background: #1890ff !important;
color: #ffffff !important;
border: none;
}
.ant-steps-icon {
color: #ffffff !important;
}
.nb-code {
margin-bottom: 1em;
}
@@ -135,4 +117,26 @@ body {
.access-control.ant-drawer-subtitle {
line-height: 22px;
margin: 24px 0;
}
.ant-steps-item-icon{
background: #EBEBEB !important;
border-color: #EBEBEB !important;
}
.ant-steps-icon-dot{
background: #EBEBEB !important;
border-color: #EBEBEB !important;
}
.ant-steps-icon {
background: #EBEBEB !important;
border: none;
color: black !important;
}
.ant-steps-item-tail::after {
background: #EBEBEB !important;
}
.ant-steps-item-tail {
border: none;
}
+18 -17
View File
@@ -1,29 +1,30 @@
export enum StorageKey {
token
token,
hadFirstRun
}
const setLocalItem = async <T>(key: StorageKey, value: T): Promise<void> => {
try {
localStorage.setItem(`@net-bird:${key}`, JSON.stringify(value));
} catch (err) {
console.log(err);
}
try {
localStorage.setItem(`@net-bird:${key}`, JSON.stringify(value));
} catch (err) {
console.log(err);
}
};
const getLocalItem = async <T>(key: StorageKey): Promise<T | null> => {
try {
const item = localStorage.getItem(`@net-bird:${key}`);
if (!item) {
return null;
try {
const item = localStorage.getItem(`@net-bird:${key}`);
if (!item) {
return null;
}
return JSON.parse(item) as T;
} catch (err) {
console.log(err);
}
return JSON.parse(item) as T;
} catch (err) {
console.log(err);
}
return null;
return null;
};
export {
getLocalItem,
setLocalItem
getLocalItem,
setLocalItem
}
Loaded 20 of 26 files, more files were not shown because too many files have changed in this diff. Show more