Compare commits

..
5 Commits
Author SHA1 Message Date
braginini 9875bb0fcd Fix setup key create popup 2023-05-07 23:16:55 +02:00
braginini ae586b4dfe Fix add PAT popup 2023-05-07 19:59:57 +02:00
braginini c0a6965310 Fix user edit view 2023-05-07 19:59:47 +02:00
braginini f12a923c61 Fix user edit view 2023-05-07 19:32:14 +02:00
braginini ad798bbab4 Fix invite and add user popups 2023-05-07 18:55:34 +02:00
65 changed files with 6687 additions and 13208 deletions

No files matched your search

+1 -2
View File
@@ -43,7 +43,6 @@ fi
export AUTH_AUTHORITY=${AUTH_AUTHORITY:-https://$AUTH0_DOMAIN}
export AUTH_CLIENT_ID=${AUTH_CLIENT_ID:-$AUTH0_CLIENT_ID}
export AUTH_CLIENT_SECRET=${AUTH_CLIENT_SECRET}
export AUTH_AUDIENCE=${AUTH_AUDIENCE:-$AUTH0_AUDIENCE}
export AUTH_REDIRECT_URI=${AUTH_REDIRECT_URI}
export AUTH_SILENT_REDIRECT_URI=${AUTH_SILENT_REDIRECT_URI}
@@ -58,7 +57,7 @@ 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_CLIENT_SECRET \$\$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"
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"
+30 -405
View File
File diff suppressed because it is too large. Load diff
-1
View File
@@ -39,7 +39,6 @@
"react-redux": "^8.0.2",
"react-router-dom": "^5.3.3",
"react-scripts": "^5.0.1",
"react-select": "^5.7.3",
"react-syntax-highlighter": "^15.5.0",
"react-table": "^7.7.0",
"redux": "^4.2.0",
+2 -2
View File
@@ -1,3 +1,3 @@
<svg width="39" height="6" viewBox="0 0 39 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.451731 2.66267C0.315048 2.79935 0.315048 3.02096 0.451731 3.15764L2.67912 5.38503C2.8158 5.52171 3.03741 5.52171 3.17409 5.38503C3.31078 5.24835 3.31078 5.02674 3.17409 4.89006L1.19419 2.91016L3.17409 0.930257C3.31078 0.793574 3.31078 0.571966 3.17409 0.435282C3.03741 0.298599 2.8158 0.298599 2.67912 0.435282L0.451731 2.66267ZM38.3807 3.15764C38.5174 3.02096 38.5174 2.79935 38.3807 2.66267L36.1533 0.435282C36.0166 0.298599 35.795 0.298599 35.6583 0.435282C35.5216 0.571966 35.5216 0.793574 35.6583 0.930257L37.6382 2.91016L35.6583 4.89006C35.5216 5.02674 35.5216 5.24835 35.6583 5.38503C35.795 5.52171 36.0166 5.52171 36.1533 5.38503L38.3807 3.15764ZM0.699219 3.26016H38.1332V2.56016H0.699219V3.26016Z" fill="#03543F"/>
<svg xmlns="http://www.w3.org/2000/svg" width="29.435" height="7.636" viewBox="0 0 29.435 7.636">
<path id="direct_bi" d="M3.64,8.158-.178,4.34,3.64.522,4.3,1.17l-2.7,2.7h25.89l-2.7-2.7.656-.648L29.257,4.34,27.213,6.384,25.439,8.158,24.783,7.5l2.7-2.693H1.595L4.3,7.5Z" transform="translate(0.178 -0.522)" fill="#1e429f"/>
</svg>

Before

Width:  |  Height:  |  Size: 837 B

After

Width:  |  Height:  |  Size: 332 B

+2 -2
View File
@@ -1,3 +1,3 @@
<svg width="39" height="6" viewBox="0 0 39 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.3807 3.15764C38.5174 3.02096 38.5174 2.79935 38.3807 2.66267L36.1533 0.435282C36.0166 0.298599 35.795 0.298599 35.6583 0.435282C35.5216 0.571966 35.5216 0.793574 35.6583 0.930257L37.6382 2.91016L35.6583 4.89006C35.5216 5.02674 35.5216 5.24835 35.6583 5.38503C35.795 5.52171 36.0166 5.52171 36.1533 5.38503L38.3807 3.15764ZM0.699219 3.26016H38.1332V2.56016H0.699219V3.26016Z" fill="#1E429F"/>
<svg xmlns="http://www.w3.org/2000/svg" width="29.497" height="7.636" viewBox="0 0 29.497 7.636">
<path id="direct_out" d="M26.589,8l-.656-.656,2.7-2.693H.91V3.713H28.635l-2.7-2.7.656-.648,3.818,3.818Z" transform="translate(-0.91 -0.364)" fill="#03543f"/>
</svg>

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 265 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.3846 3.68889C38.5213 3.55221 38.5213 3.3306 38.3846 3.19392L36.1572 0.966532C36.0205 0.829849 35.7989 0.829849 35.6622 0.966532C35.5255 1.10322 35.5255 1.32482 35.6622 1.46151L37.6421 3.44141L35.6622 5.42131C35.5255 5.55799 35.5255 5.7796 35.6622 5.91628C35.7989 6.05296 36.0205 6.05296 36.1572 5.91628L38.3846 3.68889ZM0.703125 3.79141H38.1371V3.09141H0.703125V3.79141Z" fill="#D9D9D9"/>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.615425 3.3111C0.478741 3.44779 0.478741 3.66939 0.615425 3.80608L2.84281 6.03346C2.97949 6.17015 3.2011 6.17015 3.33778 6.03346C3.47447 5.89678 3.47447 5.67517 3.33778 5.53849L1.35789 3.55859L3.33778 1.57869C3.47447 1.44201 3.47447 1.2204 3.33778 1.08372C3.2011 0.947033 2.97949 0.947033 2.84281 1.08372L0.615425 3.3111ZM38.2969 3.20859L0.862911 3.20859L0.862911 3.90859L38.2969 3.90859L38.2969 3.20859Z" fill="#2B4DA5"/>
</svg>

Before

Width:  |  Height:  |  Size: 535 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.3807 3.68889C38.5174 3.55221 38.5174 3.3306 38.3807 3.19392L36.1533 0.966532C36.0166 0.829849 35.795 0.829849 35.6583 0.966532C35.5216 1.10322 35.5216 1.32482 35.6583 1.46151L37.6382 3.44141L35.6583 5.42131C35.5216 5.55799 35.5216 5.7796 35.6583 5.91628C35.795 6.05296 36.0166 6.05296 36.1533 5.91628L38.3807 3.68889ZM0.699219 3.79141L38.1332 3.79141V3.09141L0.699219 3.09141V3.79141Z" fill="#2B4DA5"/>
</svg>

Before

Width:  |  Height:  |  Size: 517 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.3846 3.68889C38.5213 3.55221 38.5213 3.3306 38.3846 3.19392L36.1572 0.966532C36.0205 0.829849 35.7989 0.829849 35.6622 0.966532C35.5255 1.10322 35.5255 1.32482 35.6622 1.46151L37.6421 3.44141L35.6622 5.42131C35.5255 5.55799 35.5255 5.7796 35.6622 5.91628C35.7989 6.05296 36.0205 6.05296 36.1572 5.91628L38.3846 3.68889ZM0.703125 3.79141H38.1371V3.09141H0.703125V3.79141Z" fill="#03543F"/>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.615425 3.3111C0.478741 3.44779 0.478741 3.66939 0.615425 3.80608L2.84281 6.03346C2.97949 6.17015 3.2011 6.17015 3.33778 6.03346C3.47447 5.89678 3.47447 5.67517 3.33778 5.53849L1.35789 3.55859L3.33778 1.57869C3.47447 1.44201 3.47447 1.2204 3.33778 1.08372C3.2011 0.947033 2.97949 0.947033 2.84281 1.08372L0.615425 3.3111ZM38.2969 3.20859L0.862911 3.20859L0.862911 3.90859L38.2969 3.90859L38.2969 3.20859Z" fill="#D9D9D9"/>
</svg>

Before

Width:  |  Height:  |  Size: 535 B

-3
View File
@@ -1,3 +0,0 @@
<svg width="39" height="7" viewBox="0 0 39 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.615425 3.3111C0.478741 3.44779 0.478741 3.66939 0.615425 3.80608L2.84281 6.03346C2.97949 6.17015 3.2011 6.17015 3.33778 6.03346C3.47447 5.89678 3.47447 5.67517 3.33778 5.53849L1.35789 3.55859L3.33778 1.57869C3.47447 1.44201 3.47447 1.2204 3.33778 1.08372C3.2011 0.947033 2.97949 0.947033 2.84281 1.08372L0.615425 3.3111ZM38.2969 3.20859L0.862911 3.20859L0.862911 3.90859L38.2969 3.90859L38.2969 3.20859Z" fill="#03543F"/>
</svg>

Before

Width:  |  Height:  |  Size: 535 B

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -22,7 +22,7 @@ const Banner = () => {
const linkLearnMore = () => {
return (
<a
href="https://docs.netbird.io/how-to/manage-dns-in-your-network"
href="https://netbird.io/docs/how-to-guides/nameservers"
className="font-bold underline"
target="_blank"
rel="noreferrer"
+3 -3
View File
@@ -41,7 +41,7 @@ interface formNSGroup extends NameServerGroup {
const NameServerGroupUpdate = () => {
const {
blueTagRender,
tagRender,
handleChangeTags,
dropDownRender,
optionRender,
@@ -572,7 +572,7 @@ const NameServerGroupUpdate = () => {
<Select mode="tags"
style={{width: '100%'}}
placeholder="Associate groups with the NS group"
tagRender={blueTagRender}
tagRender={tagRender}
onChange={handleChangeTags}
dropdownRender={dropDownRender}
>
@@ -604,7 +604,7 @@ const NameServerGroupUpdate = () => {
<Col span={24}>
<Divider></Divider>
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank"
href="https://docs.netbird.io/how-to/manage-dns-in-your-network">Learn more about nameservers</Button>
href="https://netbird.io/docs/how-to-guides/nameservers">Learn more about nameservers</Button>
</Col>
</Row>
</Form>) :
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-466
View File
@@ -1,466 +0,0 @@
import React, { useEffect, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { actions as setupKeyActions } from "../store/setup-key";
import {
Button,
Col,
Divider,
Form,
Input,
InputNumber,
Row,
Select,
Breadcrumb,
Switch,
Tag,
Typography,
Card,
} from "antd";
import { RootState } from "typesafe-actions";
import {
FormSetupKey,
SetupKey,
SetupKeyToSave,
} from "../store/setup-key/types";
import { 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 { useGetTokenSilently } from "../utils/token";
import { expiresInToSeconds, ExpiresInValue } from "../views/ExpiresInInput";
import moment from "moment";
import { Container } from "./Container";
import Paragraph from "antd/es/typography/Paragraph";
import { EditOutlined, LockOutlined } from "@ant-design/icons";
import { actions as personalAccessTokenActions } from "../store/personal-access-token";
import { useGetGroupTagHelpers } from "../utils/groups";
const { Option } = Select;
const { Text } = Typography;
const ExpiresInDefault: ExpiresInValue = { number: 30, interval: "day" };
const customExpiresFormat = (value: Date): string | null => {
return formatDate(value);
};
const SetupKeyNew = () => {
const { optionRender, blueTagRender } = useGetGroupTagHelpers();
const { getTokenSilently } = useGetTokenSilently();
const dispatch = useDispatch();
const setupKey = useSelector((state: RootState) => state.setupKey.setupKey);
const savedSetupKey = useSelector(
(state: RootState) => state.setupKey.savedSetupKey
);
const groups = useSelector((state: RootState) => state.group.data);
const [form] = Form.useForm();
const [editName, setEditName] = useState(false);
const [tagGroups, setTagGroups] = useState([] as string[]);
const [formSetupKey, setFormSetupKey] = useState({} as FormSetupKey);
const inputNameRef = useRef<any>(null);
useEffect(() => {
//Unmounting component clean
return () => {
setVisibleNewSetupKey(false);
};
}, []);
useEffect(() => {
if (!editName) return;
inputNameRef.current!.focus({ cursor: "end" });
}, [editName]);
useEffect(() => {
setTagGroups(
groups?.filter((g) => g.name !== "All").map((g) => g.name) || []
);
}, [groups]);
useEffect(() => {
if (!setupKey) return;
const allGroups = new Map<string, Group>();
let formKeyGroups: string[] = [];
groups.forEach((g) => allGroups.set(g.id!, g));
if (setupKey.auto_groups) {
formKeyGroups = setupKey.auto_groups
.filter((g) => allGroups.get(g))
.map((g) => allGroups.get(g)!.name);
}
const fSetupKey = {
...setupKey,
autoGroupNames: setupKey.auto_groups ? formKeyGroups : [],
expiresInFormatted: ExpiresInDefault,
exp: moment(setupKey.expires),
last: moment(setupKey.last_used),
} as FormSetupKey;
form.setFieldsValue(fSetupKey);
setFormSetupKey(fSetupKey);
}, [setupKey]);
const createSetupKeyToSave = (): SetupKeyToSave => {
const autoGroups =
groups
?.filter((g) => formSetupKey.autoGroupNames.includes(g.name))
.map((g) => g.id || "") || [];
// find groups that do not yet exist (newly added by the user)
const allGroupsNames: string[] = groups?.map((g) => g.name);
const groupsToCreate = formSetupKey.autoGroupNames.filter(
(s) => !allGroupsNames.includes(s)
);
const expiresIn = expiresInToSeconds(formSetupKey.expiresInFormatted);
return {
id: formSetupKey.id,
name: formSetupKey.name,
type: formSetupKey.type,
auto_groups: autoGroups,
revoked: formSetupKey.revoked,
groupsToCreate: groupsToCreate,
expires_in: expiresIn,
usage_limit: formSetupKey.usage_limit,
} as SetupKeyToSave;
};
const handleFormSubmit = async () => {
try {
await form.validateFields();
} catch (e) {
const errorFields = (e as any).errorFields;
return console.log("errorInfo", errorFields);
}
const setupKeyToSave = createSetupKeyToSave();
dispatch(
setupKeyActions.saveSetupKey.request({
getAccessTokenSilently: getTokenSilently,
payload: setupKeyToSave,
})
);
};
const setVisibleNewSetupKey = (status: boolean) => {
form.resetFields();
dispatch(setupKeyActions.setSetupEditKeyVisible(status));
};
const onCancel = () => {
if (savedSetupKey.loading) return;
dispatch(
setupKeyActions.setSetupKey({
name: "",
type: "one-off",
key: "",
last_used: "",
expires: "",
state: "valid",
auto_groups: [] as string[],
usage_limit: 0,
used_times: 0,
expires_in: 0,
} as SetupKey)
);
setFormSetupKey({} as FormSetupKey);
setVisibleNewSetupKey(false);
};
const onChange = (data: any) => {
setFormSetupKey({ ...formSetupKey, ...data });
};
const toggleEditName = (status: boolean) => {
setEditName(status);
};
const selectValidator = (_: RuleObject, value: string[]) => {
let hasSpaceNamed = [];
value.forEach(function (v: string) {
if (!v.trim().length) {
hasSpaceNamed.push(v);
}
});
if (hasSpaceNamed.length) {
return Promise.reject(
new Error("Group names with just spaces are not allowed")
);
}
return Promise.resolve();
};
const dropDownRender = (menu: React.ReactElement) => (
<>
{menu}
<Divider style={{ margin: "8px 0" }} />
<Row style={{ padding: "0 8px 4px" }}>
<Col flex="auto">
<span style={{ color: "#9CA3AF" }}>
Add new group by pressing "Enter"
</span>
</Col>
<Col flex="none">
<svg
width="14"
height="12"
viewBox="0 0 14 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.70455 7.19176V5.89915H10.3949C10.7727 5.89915 11.1174 5.80634 11.429 5.62074C11.7405 5.43513 11.9875 5.18655 12.1697 4.875C12.3554 4.56345 12.4482 4.21875 12.4482 3.84091C12.4482 3.46307 12.3554 3.12003 12.1697 2.81179C11.9841 2.50024 11.7356 2.25166 11.424 2.06605C11.1158 1.88044 10.7727 1.78764 10.3949 1.78764H9.83807V0.5H10.3949C11.0114 0.5 11.5715 0.650805 12.0753 0.952414C12.5791 1.25402 12.9818 1.65672 13.2834 2.16051C13.585 2.6643 13.7358 3.22443 13.7358 3.84091C13.7358 4.30161 13.648 4.73414 13.4723 5.13849C13.3 5.54285 13.0613 5.89915 12.7564 6.20739C12.4515 6.51562 12.0968 6.75758 11.6925 6.93324C11.2881 7.10559 10.8556 7.19176 10.3949 7.19176H1.70455ZM4.90128 11.0646L0.382102 6.54545L4.90128 2.02628L5.79119 2.91619L2.15696 6.54545L5.79119 10.1747L4.90128 11.0646Z"
fill="#9CA3AF"
/>
</svg>
</Col>
</Row>
</>
);
const changesDetected = (): boolean => {
return (
formSetupKey.name == null ||
formSetupKey.name !== setupKey.name ||
groupsChanged() ||
formSetupKey.usage_limit !== setupKey.usage_limit
);
};
const groupsChanged = (): boolean => {
if (
setupKey &&
setupKey.auto_groups &&
formSetupKey.autoGroupNames.length !== setupKey.auto_groups.length
) {
return true;
}
const formGroupIds =
groups
?.filter((g) => formSetupKey.autoGroupNames.includes(g.name))
.map((g) => g.id || "") || [];
return (
setupKey.auto_groups?.filter((g) => !formGroupIds.includes(g)).length > 0
);
};
const getFormKey = (key: string) => {
if (key) return key.substring(0, 4).concat("****");
};
const onBreadcrumbUsersClick = () => {
if (savedSetupKey.loading) return;
// dispatch(userActions.setUser(null as unknown as User));
dispatch(personalAccessTokenActions.resetPersonalAccessTokens(null));
setVisibleNewSetupKey(false);
};
return (
<>
<Breadcrumb
style={{ marginBottom: "25px" }}
items={[
{
title: <a onClick={onBreadcrumbUsersClick}>Setup Keys</a>,
},
{
title: setupKey.name,
},
]}
/>
<Card bordered={true} style={{ marginBottom: "7px", border: "none" }}>
<div style={{ maxWidth: "800px" }}>
<h3 style={{ fontSize: "22px", fontWeight: "500",marginBottom:"30px" }}>
{setupKey.name}
</h3>
<Form
layout="vertical"
requiredMark={false}
form={form}
onValuesChange={onChange}
initialValues={{
expiresIn: ExpiresInDefault,
usage_limit: 1,
}}
>
<Row style={{ marginTop: "10px" }}>
<Col
xs={24}
sm={24}
md={11}
lg={11}
xl={11}
xxl={11}
span={11}
style={{ paddingRight: "70px" }}
>
<Paragraph
style={{
whiteSpace: "pre-line",
fontWeight: "500",
margin: 0,
}}
>
Key
<Tag
color={`${
formSetupKey.state === "valid" ? "green" : "red"
}`}
style={{
marginLeft: "10px",
borderRadius: "2px",
fontWeight: "500",
}}
>
{formSetupKey.state}
</Tag>
</Paragraph>
<Input
style={{ marginTop: "8px" }}
disabled
value={getFormKey(formSetupKey.key)}
suffix={<LockOutlined style={{ color: "#BFBFBF" }} />}
/>
</Col>
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>
<Paragraph
style={{
whiteSpace: "pre-line",
margin: 0,
fontWeight: "500",
}}
>
<Paragraph
style={{
whiteSpace: "pre-line",
margin: 0,
fontWeight: "500",
}}
></Paragraph>
{formSetupKey.type === "one-off" ? "One-off" : "Reusable"},
available uses
</Paragraph>
<Col>
<Input
disabled
value={
formSetupKey.type === "reusable" &&
formSetupKey.usage_limit === 0
? "unlimited"
: formSetupKey.usage_limit - formSetupKey.used_times
}
suffix={<LockOutlined style={{ color: "#BFBFBF" }} />}
style={{ marginTop: "8px" }}
/>
</Col>
</Col>
</Row>
<Row style={{ marginTop: "30px" }}>
<Col
xs={24}
sm={24}
md={11}
lg={11}
xl={11}
xxl={11}
span={11}
style={{ paddingRight: "70px" }}
>
<Paragraph
style={{
whiteSpace: "pre-line",
margin: 0,
fontWeight: "500",
}}
>
Auto-assigned groups
</Paragraph>
<Col span={24}>
<Form.Item
style={{ marginTop: "8px", marginBottom: 0 }}
name="autoGroupNames"
rules={[{ validator: selectValidator }]}
>
<Select
mode="tags"
style={{ width: "100%" }}
placeholder="Associate groups with the key"
tagRender={blueTagRender}
dropdownRender={dropDownRender}
// enabled only when we have a new key !setupkey.id or when the key is valid
disabled={!(!setupKey.id || setupKey.valid)}
>
{tagGroups.map((m) => (
<Option key={m}>{optionRender(m)}</Option>
))}
</Select>
</Form.Item>
</Col>
</Col>
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>
<Paragraph style={{ margin: 0, fontWeight: "500" }}>
Expires
</Paragraph>
<Row>
<Input
style={{ marginTop: "8px" }}
disabled
suffix={<LockOutlined style={{ color: "#BFBFBF" }} />}
value={customExpiresFormat(new Date(formSetupKey.expires))!}
/>
</Row>
</Col>
</Row>
<Row style={{ marginTop: "40px", marginBottom: "28px" }}>
<Text type={"secondary"}>
Learn more about
<a
target="_blank"
rel="noreferrer"
href="https://docs.netbird.io/how-to/register-machines-using-setup-keys"
>
{" "}
Setup Keys
</a>
</Text>
</Row>
</Form>
</div>
<Container
style={{
display: "flex",
flexDirection: "row",
justifyContent: "start",
padding: 0,
gap: "10px",
}}
key={0}
>
<Button onClick={onCancel}>Cancel</Button>
<Button
type="primary"
disabled={savedSetupKey.loading || !changesDetected()}
onClick={handleFormSubmit}
>
{`${formSetupKey.id ? "Save" : "Create"} key`}
</Button>
</Container>
</Card>
</>
);
};
export default SetupKeyNew;
Loaded 20 of 65 files, more files were not shown because too many files have changed in this diff. Show more