Compare commits

..
14 Commits
Author SHA1 Message Date
Misha Bragin 7a29dac01c Add single line installer command for Mac and Linux (#162) 2023-04-04 14:20:02 +02:00
pascal-fischer 444e9ec44a fetch userID from user list and not oidc by default (#161) 2023-04-03 16:52:42 +02:00
pascal-fischer dff0313f82 Feature/pat support (#157)
* Add working UI + API calls [missing token popup]

* use popup view to add new token

* show userID if user name not available

* switch from description to name

* show "Me" instead of own name

* removed created_by column

* update add token explanation

* use object instead of plain text for token create response

* some style changes

* disable information button for tokens

* last_used can contain nil

* fix delete popups

* lower case letters for dates

* add activity and fix visibility

* show settings tab for non admins

* remove spaces on top of setting tabs

* fix copy button size and position

* fix list footers

* continue merge changes to new files
2023-04-03 12:29:40 +02:00
Maycon Santos 11fbfb336a Clean last estimated name (#160) 2023-04-03 12:16:12 +02:00
Maycon Santos 4a0ae8f27d Add missing config change (#159) 2023-04-01 21:58:46 +02:00
Maycon Santos 9a72d8b0c4 Allow defining API token source (#158)
On many IDP providers, the access token
 is used to access the IDP's own API

 With these changes, we allow users to define the proper token to be used for
 management API calls
2023-04-01 19:44:28 +02:00
Misha Bragin 8e038cf242 Make table headers font-weight normal (#156) 2023-03-27 15:59:18 +02:00
Misha Bragin 5bd94eff56 Fix add peer popup tab layout on mobile (#154) 2023-03-23 12:10:27 +01:00
Misha Bragin 77f065b093 Update theme border radius (#152) 2023-03-22 16:56:36 +01:00
Misha Bragin a4d55cfb90 Fix settings modal styles (#151) 2023-03-22 16:14:49 +01:00
Misha Bragin cfd4c9075b Add onboarding steps (#150) 2023-03-22 15:21:52 +01:00
braginini 962180030a Fix activity docs link 2023-03-15 14:20:48 +01:00
Misha Bragin 485e1e8d79 Add more references to docs (#149) 2023-03-15 14:18:22 +01:00
Givi Khojanashvili b11007b29f Add policy add activities (#147)
Related changes for netbirdio/netbird#700
2023-03-13 10:58:34 +01:00
49 changed files with 2499 additions and 958 deletions

No files matched your search

+2 -1
View File
@@ -52,11 +52,12 @@ export AUTH_SUPPORTED_SCOPES=${AUTH_SUPPORTED_SCOPES:-openid profile email api o
export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
export NETBIRD_MGMT_GRPC_API_ENDPOINT=${NETBIRD_MGMT_GRPC_API_ENDPOINT}
export NETBIRD_HOTJAR_TRACK_ID=${NETBIRD_HOTJAR_TRACK_ID}
export NETBIRD_TOKEN_SOURCE=${NETBIRD_TOKEN_SOURCE:-accessToken}
echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"
# replace ENVs in the config
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI"
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE"
MAIN_JS=$(find /usr/share/nginx/html/static/js/main.*js)
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
+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",
+58 -48
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";
@@ -16,7 +16,7 @@ import SetupKeys from "./views/SetupKeys";
import AccessControl from "./views/AccessControl";
import Users from "./views/Users";
import FooterComponent from "./components/FooterComponent";
import {useGetAccessTokenSilently} from "./utils/token";
import {useGetTokenSilently, useTokenSource} from "./utils/token";
import {User} from "./store/user/types";
import {SecureLoading} from "./components/Loading";
import DNS from "./views/DNS";
@@ -24,14 +24,14 @@ import Activity from "./views/Activity";
import Settings from "./views/Settings";
const {Header, Content} = Layout;
function App() {
const run = useRef(false)
const [show, setShow] = useState(false)
const {getAccessTokenSilently} = useGetAccessTokenSilently();
const {hotjarTrackID} = getConfig();
const {hotjarTrackID,tokenSource} = getConfig();
useTokenSource(tokenSource)
const {getTokenSilently} = useGetTokenSilently();
// @ts-ignore
if (hotjarTrackID && window._DATADOG_SYNTHETICS_BROWSER === undefined) {
hotjar.initialize(hotjarTrackID, 6);
@@ -56,9 +56,9 @@ function App() {
useEffect(() => {
if (!run.current) {
run.current = true
apiClient.request<User[]>('GET', `/api/users`, {getAccessTokenSilently: getAccessTokenSilently})
apiClient.request<User[]>('GET', `/api/users`, {getAccessTokenSilently: getTokenSilently})
.then(() => {
setShow(true)
setShow(true)
})
.catch(e => {
setShow(true)
@@ -66,55 +66,65 @@ function App() {
})
}
}, [getAccessTokenSilently])
}, [getTokenSilently])
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>
</>
)
}
+4 -6
View File
@@ -23,7 +23,7 @@ import {Rule, RuleToSave} from "../store/rule/types";
import {uniq} from "lodash"
import {Header} from "antd/es/layout/layout";
import {RuleObject} from "antd/lib/form";
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
const {Paragraph} = Typography;
const {Option} = Select;
@@ -34,7 +34,7 @@ interface FormRule extends Rule {
}
const AccessControlNew = () => {
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const setupNewRuleVisible = useSelector((state: RootState) => state.rule.setupNewRuleVisible)
const groups = useSelector((state: RootState) => state.group.data)
@@ -103,7 +103,7 @@ const AccessControlNew = () => {
.then((values) => {
const ruleToSave = createRuleToSave()
dispatch(ruleActions.saveRule.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: ruleToSave
}))
})
@@ -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>
+4 -6
View File
@@ -32,7 +32,7 @@ import {RuleObject} from "antd/lib/form";
import cidrRegex from 'cidr-regex';
import {NameServer, NameServerGroup, NameServerGroupToSave} from "../store/nameservers/types";
import {useGetGroupTagHelpers} from "../utils/groups"
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
const {Paragraph} = Typography;
@@ -51,7 +51,7 @@ const NameServerGroupUpdate = () => {
selectValidator
} = useGetGroupTagHelpers()
const dispatch = useDispatch()
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const {Option} = Select;
const nsGroup = useSelector((state: RootState) => state.nameserverGroup.nameserverGroup)
const setupNewNameServerGroupVisible = useSelector((state: RootState) => state.nameserverGroup.setupNewNameServerGroupVisible)
@@ -220,7 +220,7 @@ const NameServerGroupUpdate = () => {
.then((values) => {
const nsGroupToSave = createNSGroupToSave(values as NameServerGroup)
dispatch(nsGroupActions.saveNameServerGroup.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: nsGroupToSave
}))
@@ -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>) :
+4 -5
View File
@@ -11,7 +11,7 @@ import {User} from "../store/user/types";
import {useDispatch, useSelector} from "react-redux";
import {RootState} from "typesafe-actions";
import {actions as userActions} from "../store/user";
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
const {useBreakpoint} = Grid;
@@ -19,7 +19,7 @@ const Navbar = () => {
let location = useLocation();
const config = getConfig();
const { logout } = useOidc();
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const {oidcUser} = useOidcUser();
@@ -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'},
@@ -48,7 +47,7 @@ const Navbar = () => {
const userEmailKey = 'user-email'
const userLogoutKey = 'user-logout'
const userDividerKey = 'user-divider'
const adminOnlyTabs = ["/setup-keys", "/acls", "/routes", "/dns", "/activity", "/settings"]
const adminOnlyTabs = ["/setup-keys", "/acls", "/routes", "/dns", "/activity"]
const [menuItems, setMenuItems] = useState(items)
const logoutWithRedirect = () =>
logout("/", {client_id: config.clientId});
@@ -81,7 +80,7 @@ const Navbar = () => {
window.location.pathname !== '/peers' &&
window.location.pathname !== '/users') {
setIsRefreshingUserState(true)
dispatch(userActions.getUsers.request({getAccessTokenSilently: getAccessTokenSilently, payload: null}))
dispatch(userActions.getUsers.request({getAccessTokenSilently: getTokenSilently, payload: null}))
return
}
if (users.length === 0 && isRefreshingUserState) {
+5 -4
View File
@@ -9,7 +9,7 @@ import {FormPeer, Peer, PeerGroupsToSave} from "../store/peer/types";
import {Group, GroupPeer} from "../store/group/types";
import {CloseOutlined, EditOutlined} from "@ant-design/icons";
import {RuleObject} from 'antd/lib/form';
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
import {timeAgo} from "../utils/common";
const {Paragraph} = Typography;
@@ -19,7 +19,7 @@ const punycode = require('punycode/')
const PeerUpdate = () => {
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const groups = useSelector((state: RootState) => state.group.data)
const users = useSelector((state: RootState) => state.user.data)
@@ -191,6 +191,7 @@ const PeerUpdate = () => {
setCallingPeerAPI(false)
setCallingPeerAPI(false)
setSubmitRunning(false)
setEstimatedName("")
}
const noUpdateToGroups = (): Boolean => {
@@ -250,14 +251,14 @@ const PeerUpdate = () => {
const peerUpdate = createPeerToSave()
setCallingPeerAPI(true)
dispatch(peerActions.updatePeer.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: peerUpdate
}))
}
if (!noUpdateToGroups()) {
setCallingGroupAPI(true)
dispatch(peerActions.saveGroups.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: peerGroupsToSave
}))
}
+5 -7
View File
@@ -30,7 +30,7 @@ import {
routePeerSeparator,
transformGroupedDataTable
} from '../utils/routes'
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
import {useGetGroupTagHelpers} from "../utils/groups";
const {Paragraph} = Typography;
@@ -50,7 +50,7 @@ const RouteUpdate = () => {
selectValidator
} = useGetGroupTagHelpers()
const {Option} = Select;
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const setupNewRouteVisible = useSelector((state: RootState) => state.route.setupNewRouteVisible)
const setupNewRouteHA = useSelector((state: RootState) => state.route.setupNewRouteHA)
@@ -163,7 +163,7 @@ const RouteUpdate = () => {
if (!setupNewRouteHA || formRoute.peer != '') {
const routeToSave = createRouteToSave(formRoute)
dispatch(routeActions.saveRoute.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: routeToSave
}))
} else {
@@ -180,7 +180,7 @@ const RouteUpdate = () => {
}
const routeToSave = createRouteToSave(updateRoute)
dispatch(routeActions.saveRoute.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: routeToSave
}))
})
@@ -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>
+13 -11
View File
@@ -11,7 +11,7 @@ import {
Form,
Input,
InputNumber,
List,
List, Modal,
Radio,
Row,
Select,
@@ -27,8 +27,9 @@ import {checkExpiresIn, formatDate, timeAgo} from "../utils/common";
import {RuleObject} from "antd/lib/form";
import {CustomTagProps} from "rc-select/lib/BaseSelect";
import {Group} from "../store/group/types";
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} 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())
@@ -52,7 +54,7 @@ const customLastUsedFormat: DatePickerProps['format'] = value => {
}
const SetupKeyNew = () => {
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const setupNewKeyVisible = useSelector((state: RootState) => state.setupKey.setupNewKeyVisible)
const setupKey = useSelector((state: RootState) => state.setupKey.setupKey)
@@ -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)
@@ -123,7 +127,7 @@ const SetupKeyNew = () => {
.then((values) => {
let setupKeyToSave = createSetupKeyToSave()
dispatch(setupKeyActions.saveSetupKey.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: setupKeyToSave
}))
})
@@ -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>
+4 -4
View File
@@ -9,7 +9,7 @@ import {FormUser, User, UserToSave} from "../store/user/types";
import {RuleObject} from "antd/lib/form";
import {CustomTagProps} from "rc-select/lib/BaseSelect";
import {actions as userActions} from "../store/user";
import {useGetAccessTokenSilently} from "../utils/token";
import {useGetTokenSilently} from "../utils/token";
import {useOidcUser} from "@axa-fr/react-oidc";
const {Paragraph} = Typography;
@@ -20,7 +20,7 @@ const {Option} = Select;
const UserUpdate = () => {
const {oidcUser} = useOidcUser();
const {getAccessTokenSilently} = useGetAccessTokenSilently()
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const user = useSelector((state: RootState) => state.user.user)
const savedUser = useSelector((state: RootState) => state.user.savedUser)
@@ -193,7 +193,7 @@ const UserUpdate = () => {
okType: 'danger',
onOk() {
dispatch(userActions.saveUser.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: userToSave
}))
},
@@ -215,7 +215,7 @@ const UserUpdate = () => {
showConfirmChangeRole(userToSave)
} else {
dispatch(userActions.saveUser.request({
getAccessTokenSilently: getAccessTokenSilently,
getAccessTokenSilently: getTokenSilently,
payload: userToSave
}))
}
+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}/>Linux</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
+64 -15
View File
@@ -1,18 +1,50 @@
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";
import SyntaxHighlighter from "react-syntax-highlighter";
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 +76,37 @@ 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 with one command
</Text>
<div style={{fontSize: ".85em", marginTop: 5, marginBottom: 25}}>
<SyntaxHighlighter language="bash">
curl -fsSL https://pkgs.netbird.io/install.sh | sh
</SyntaxHighlighter>
</div>
<Text style={{fontWeight: "bold"}}>
Or install manually with HomeBrew
</Text>
<div style={{marginTop: 5}}>
<TabSteps stepsItems={steps}/>
</div>
</div>
/*<div style={{marginTop: 5}}>
<TabSteps stepsItems={quickSteps}/>
</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>
}
/>
+31 -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,36 @@ 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://pkgs.netbird.io/install.sh | sh
</SyntaxHighlighter>
</div>
<Text style={{fontWeight: "bold"}}>
Or install manually 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

Loaded 20 of 49 files, more files were not shown because too many files have changed in this diff. Show more