mirror of
https://github.com/netbirdio/dashboard.git
synced 2026-09-23 00:30:43 -07:00
Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4612f6c49a | ||
|
|
a3a0e6315f | ||
|
|
fa7bc205ba | ||
|
|
87ff65f1a7 | ||
|
|
748596f710 | ||
|
|
b06cb0ec3d | ||
|
|
0c924f7ded | ||
|
|
f29c915fc2 | ||
|
|
5f8579bfda | ||
|
|
a71389aa29 | ||
|
|
c3ba026452 | ||
|
|
193f8a7bdf | ||
|
|
f9814e1169 | ||
|
|
2f800bf912 | ||
|
|
0199ea81f3 | ||
|
|
a20894092b | ||
|
|
f4d6ce5770 | ||
|
|
dd67ab6dcb | ||
|
|
2613948cdf | ||
|
|
dc95d8bfd1 | ||
|
|
f49c28f550 | ||
|
|
2fc7b73ea0 | ||
|
|
a9354d3c87 | ||
|
|
e0ae7d068a | ||
|
|
ddd812e9a0 | ||
|
|
2d55d0736f | ||
|
|
8febc26f1f | ||
|
|
3f854b01a0 | ||
|
|
303d51eff8 | ||
|
|
21e69e642a | ||
|
|
835bb37ab9 | ||
|
|
a944dc8ab0 | ||
|
|
b2c51533fb | ||
|
|
fd24536926 | ||
|
|
8e8484cd45 |
No files matched your search
@@ -0,0 +1,15 @@
|
||||
name: Codespell
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: codespell
|
||||
uses: codespell-project/actions-codespell@v2
|
||||
with:
|
||||
only_warn: 1
|
||||
skip: package-lock.json,*.svg
|
||||
+3
-3
@@ -1,15 +1,15 @@
|
||||
# Wiretrustee Dashboard
|
||||
Wiretrustee Dashboard is a the Wiretrustee Managemenet server UI. It allow users to signin, view setup keys and manage peers. This image is **not ready** for production use.
|
||||
Wiretrustee Dashboard is a the Wiretrustee Management server UI. It allow users to signin, view setup keys and manage peers. This image is **not ready** for production use.
|
||||
## Tags
|
||||
```latest``` ```vX.X.X``` not available yet.
|
||||
|
||||
```main``` builded on every PR being merged to the repository
|
||||
```main``` built on every PR being merged to the repository
|
||||
## How to use this image
|
||||
HTTP run:
|
||||
```shell
|
||||
docker run -d --rm -p 80:80 wiretrustee/dashboard:main
|
||||
```
|
||||
Using SSL certificate from Let's Encript®:
|
||||
Using SSL certificate from Let's Encrypt®:
|
||||
```shell
|
||||
docker run -d --rm -p 80:80 -p 443:443 \
|
||||
-e LETSENCRYPT_DOMAIN=app.mydomain.com \
|
||||
|
||||
@@ -387,7 +387,7 @@ check_nb_domain() {
|
||||
|
||||
if [ "$DOMAIN" == "netbird.example.com" ]; then
|
||||
echo "The NETBIRD_DOMAIN cannot be netbird.example.com" > /dev/stderr
|
||||
retrun 1
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export class AccessControlPage {
|
||||
}
|
||||
|
||||
async assertDefaultAccessCotrolIsCreated() {
|
||||
await test.step('Assert that default cotrol access is created', async () => {
|
||||
await test.step('Assert that default control access is created', async () => {
|
||||
await expect(this.defaulAccessControl).toBeVisible();
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ export class AddPeerModal {
|
||||
private readonly windowsTab = this.page.getByTestId('add-peer-modal-windows-tab')
|
||||
private readonly macTab = this.page.getByTestId('add-peer-modal-mac-tab')
|
||||
private readonly androidTab = this.page.getByTestId('add-peer-modal-android-tab')
|
||||
private readonly iosTab = this.page.getByTestId('add-peer-modal-ios-tab')
|
||||
private readonly dockerTab = this.page.getByTestId('add-peer-modal-docker-tab')
|
||||
private readonly linuxTabText = this.page.locator('pre').filter({ hasText: 'curl -fsSL https://pkgs.netbird.io/install.sh | sh' })
|
||||
private readonly windowsDownloadButton = this.page.getByTestId('download-windows-button')
|
||||
@@ -57,6 +58,13 @@ export class AddPeerModal {
|
||||
})
|
||||
}
|
||||
|
||||
async openIOSTab() {
|
||||
await test.step('Open iOS tab on add peer modal', async () => {
|
||||
await this.iosTab.click();
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
async openDockerTab() {
|
||||
await test.step('Open Docker tab on add peer modal', async () => {
|
||||
await this.dockerTab.click();
|
||||
@@ -94,6 +102,12 @@ export class AddPeerModal {
|
||||
})
|
||||
}
|
||||
|
||||
async assertiOSDownloadButtonHasCorrectLink() {
|
||||
await test.step('Assert iOS download button has a correct link', async () => {
|
||||
await expect(this.androidDownloadButton).toHaveAttribute('href', 'https://apps.apple.com/app/netbird-p2p-vpn/id6469329339');
|
||||
})
|
||||
}
|
||||
|
||||
async assertDockerDownloadButtonHasCorrectLink() {
|
||||
await test.step('Assert Docker download button has a correct link', async () => {
|
||||
await expect(this.dockerDownloadButton).toHaveAttribute('href', 'https://docs.docker.com/engine/install/');
|
||||
|
||||
@@ -30,6 +30,11 @@ test('Test MacOS tab on a first access add peer modal / @bc', async () => {
|
||||
await addPeerModal.assertM1M2DownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
test('Test iOS tab on a first access add peer modal', async () => {
|
||||
await addPeerModal.openIOSTab();
|
||||
await addPeerModal.assertiOSDownloadButtonHasCorrectLink();
|
||||
});
|
||||
|
||||
test('Test Android tab on a first access add peer modal', async () => {
|
||||
await addPeerModal.openAndroidTab();
|
||||
await addPeerModal.assertAndroidDownloadButtonHasCorrectLink();
|
||||
|
||||
Generated
+6
-6
@@ -63,9 +63,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz",
|
||||
"integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g=="
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz",
|
||||
"integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg=="
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
@@ -17173,9 +17173,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@adobe/css-tools": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz",
|
||||
"integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g=="
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz",
|
||||
"integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg=="
|
||||
},
|
||||
"@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import {SecureLoading} from "./components/Loading";
|
||||
import DNS from "./views/DNS";
|
||||
import Activity from "./views/Activity";
|
||||
import Settings from "./views/Settings";
|
||||
import {isLocalDev, isNetBirdHosted} from "./utils/common";
|
||||
|
||||
|
||||
const {Header, Content} = Layout;
|
||||
@@ -75,7 +76,7 @@ function App() {
|
||||
{!show && <SecureLoading padding="3em" width={50} height={50}/>}
|
||||
{show &&
|
||||
<Layout>
|
||||
<Banner/>
|
||||
{(isNetBirdHosted() || isLocalDev()) && <Banner/>}
|
||||
<Header className="header" style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -15,18 +15,20 @@ const Banner = () => {
|
||||
localStorage.setItem(banner_closed_key,'true');
|
||||
};
|
||||
|
||||
const announcement = "New Release! Manage DNS with NetBird."
|
||||
// todo: when updating this announcement, ensure to
|
||||
// remove the condition on App.tsx that limits the current banner to cloud and local dev
|
||||
const announcement = "Discover the new NetBird Dashboard with a brand new look and feel."
|
||||
|
||||
const announcement_md5 = Md5.hashStr(announcement)
|
||||
|
||||
const linkLearnMore = () => {
|
||||
return (
|
||||
<a
|
||||
href="https://docs.netbird.io/how-to/manage-dns-in-your-network"
|
||||
href="https://preview.netbird.io/peers"
|
||||
className="font-bold underline"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
><Text strong style={{color: "#ffffff"}}>Learn more <span aria-hidden="true">→</span></Text></a>
|
||||
><Text strong style={{color: "#ffffff"}}>Try it out now <span aria-hidden="true">→</span></Text></a>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,7 +38,7 @@ const Banner = () => {
|
||||
|
||||
if((!stored_banner_closed || stored_banner_closed !== 'true') ||
|
||||
(!store_banner_md5 || store_banner_md5 !== announcement_md5)) {
|
||||
//setShow(true);
|
||||
setShow(true);
|
||||
localStorage.setItem(banner_md5_key,announcement_md5);
|
||||
localStorage.setItem(banner_closed_key,'false');
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ const NameServerGroupAdd = () => {
|
||||
const inputNameRef = useRef<any>(null);
|
||||
const inputDescriptionRef = useRef<any>(null);
|
||||
const [selectCustom, setSelectCustom] = useState(false);
|
||||
const [matchDomains, setMatchDomains] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (editName)
|
||||
@@ -87,7 +88,6 @@ const NameServerGroupAdd = () => {
|
||||
cursor: "end",
|
||||
});
|
||||
}, [editDescription]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!nsGroup) return;
|
||||
|
||||
@@ -117,6 +117,7 @@ const NameServerGroupAdd = () => {
|
||||
nameservers: [] as NameServer[],
|
||||
groups: [],
|
||||
enabled: false,
|
||||
search_domains_enabled: false,
|
||||
} as NameServerGroup)
|
||||
);
|
||||
setEditName(false);
|
||||
@@ -125,6 +126,7 @@ const NameServerGroupAdd = () => {
|
||||
};
|
||||
|
||||
const onChange = (changedValues: any) => {
|
||||
|
||||
if (changedValues.primary !== undefined) {
|
||||
setIsPrimary(changedValues.primary);
|
||||
}
|
||||
@@ -156,6 +158,7 @@ const NameServerGroupAdd = () => {
|
||||
],
|
||||
groups: [],
|
||||
enabled: true,
|
||||
search_domains_enabled: false,
|
||||
},
|
||||
{
|
||||
name: cloudflareChoice,
|
||||
@@ -176,6 +179,7 @@ const NameServerGroupAdd = () => {
|
||||
],
|
||||
groups: [],
|
||||
enabled: true,
|
||||
search_domains_enabled: false,
|
||||
},
|
||||
{
|
||||
name: quad9Choice,
|
||||
@@ -196,6 +200,7 @@ const NameServerGroupAdd = () => {
|
||||
],
|
||||
groups: [],
|
||||
enabled: true,
|
||||
search_domains_enabled: false,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -203,6 +208,7 @@ const NameServerGroupAdd = () => {
|
||||
let nsGroupLocal = {} as NameServerGroup;
|
||||
if (value === customChoice) {
|
||||
nsGroupLocal = nsGroup;
|
||||
nsGroupLocal.domains = [];
|
||||
} else {
|
||||
defaultDNSOptions.forEach((nsg) => {
|
||||
if (value === nsg.name) {
|
||||
@@ -262,6 +268,8 @@ const NameServerGroupAdd = () => {
|
||||
groups: existingGroups,
|
||||
groupsToCreate: newGroups,
|
||||
enabled: values.enabled,
|
||||
search_domains_enabled:
|
||||
matchDomains > 0 ? formNSGroup.search_domains_enabled : false,
|
||||
} as NameServerGroupToSave;
|
||||
};
|
||||
|
||||
@@ -462,6 +470,7 @@ const NameServerGroupAdd = () => {
|
||||
</Col>
|
||||
</Space>
|
||||
</Row>
|
||||
{setMatchDomains(fields.length)}
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Row key={index} style={{ marginBottom: "5px" }}>
|
||||
@@ -522,6 +531,13 @@ const NameServerGroupAdd = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeMarkDomain = (checked: boolean) => {
|
||||
setFormNSGroup({
|
||||
...formNSGroup,
|
||||
search_domains_enabled: checked,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{nsGroup && (
|
||||
@@ -701,6 +717,46 @@ const NameServerGroupAdd = () => {
|
||||
<Col span={24}>
|
||||
<Form.List name="domains">{renderDomains}</Form.List>
|
||||
</Col>
|
||||
|
||||
{matchDomains > 0 && (
|
||||
<Col span={24}>
|
||||
<Form.Item name="search_domains_enabled" label="">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "15px",
|
||||
}}
|
||||
>
|
||||
<Switch
|
||||
onChange={handleChangeMarkDomain}
|
||||
size="small"
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Mark match domains as search domains
|
||||
</label>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
}}
|
||||
>
|
||||
E.g., "peer.example.com" will be accessible with
|
||||
"peer"
|
||||
</Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
)}
|
||||
<Col span={24}>
|
||||
<label
|
||||
style={{
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -161,7 +161,7 @@ const Navbar = () => {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.role?.toLowerCase() === "admin") {
|
||||
if (user.role?.toLowerCase() === "admin" || user.role?.toLowerCase() === "owner") {
|
||||
return true;
|
||||
}
|
||||
return !adminOnlyTabs.find((t) => t === key);
|
||||
|
||||
@@ -197,6 +197,7 @@ const PeerUpdate = (props: any) => {
|
||||
os !== "" &&
|
||||
!os.toLowerCase().startsWith("darwin") &&
|
||||
!os.toLowerCase().startsWith("windows") &&
|
||||
!os.toLowerCase().startsWith("ios") &&
|
||||
!os.toLowerCase().startsWith("android")
|
||||
);
|
||||
};
|
||||
|
||||
@@ -151,6 +151,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
!os.toLowerCase().startsWith("darwin") &&
|
||||
!os.toLowerCase().startsWith("windows") &&
|
||||
!os.toLowerCase().startsWith("android") &&
|
||||
!os.toLowerCase().startsWith("ios") &&
|
||||
route &&
|
||||
!routes
|
||||
.filter((r) => r.network_id === route.network_id)
|
||||
@@ -363,7 +364,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
|
||||
const peerGroupsValidaton = (_: RuleObject, value: string) => {
|
||||
if (value.length < 1) {
|
||||
return Promise.reject(new Error("Please select peer groups"));
|
||||
return Promise.reject(new Error("Please select a peer group"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
@@ -100,6 +100,7 @@ const RoutePeerUpdate = () => {
|
||||
!os.toLowerCase().startsWith("darwin") &&
|
||||
!os.toLowerCase().startsWith("windows") &&
|
||||
!os.toLowerCase().startsWith("android") &&
|
||||
!os.toLowerCase().startsWith("ios") &&
|
||||
route &&
|
||||
!routes
|
||||
.filter((r) => r.network_id === route.network_id)
|
||||
@@ -113,15 +114,15 @@ const RoutePeerUpdate = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const handleSingleChangeTags = (values: any) => {
|
||||
const lastValue = values[values.length - 1];
|
||||
if (values.length > 0) {
|
||||
form.setFieldsValue({
|
||||
peer_groups: [lastValue],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSingleChangeTags = (values: any) => {
|
||||
const lastValue = values[values.length - 1];
|
||||
if (values.length > 0) {
|
||||
form.setFieldsValue({
|
||||
peer_groups: [lastValue],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const createRouteToSave = (inputRoute: FormRoute): RouteToSave => {
|
||||
if (inputRoute.peer_groups) {
|
||||
inputRoute = {
|
||||
@@ -367,7 +368,7 @@ const RoutePeerUpdate = () => {
|
||||
},
|
||||
{
|
||||
key: "groupOfPeers",
|
||||
label: "Peer groups",
|
||||
label: "Peer group",
|
||||
disabled: true,
|
||||
children: (
|
||||
<>
|
||||
|
||||
@@ -96,6 +96,7 @@ const RouteAddNew = () => {
|
||||
!os.toLowerCase().startsWith("darwin") &&
|
||||
!os.toLowerCase().startsWith("windows") &&
|
||||
!os.toLowerCase().startsWith("android") &&
|
||||
!os.toLowerCase().startsWith("ios") &&
|
||||
route &&
|
||||
!routes
|
||||
.filter((r) => r.network_id === route.network_id)
|
||||
@@ -166,24 +167,21 @@ const RouteAddNew = () => {
|
||||
return payload;
|
||||
};
|
||||
|
||||
const handleSingleChangeTags = (values: any) => {
|
||||
const lastValue = values[values.length - 1];
|
||||
if (values.length > 0) {
|
||||
form.setFieldsValue({
|
||||
peer_groups: [lastValue],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSingleChangeTags = (values: any) => {
|
||||
const lastValue = values[values.length - 1];
|
||||
if (values.length > 0) {
|
||||
form.setFieldsValue({
|
||||
peer_groups: [lastValue],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormSubmit = () => {
|
||||
form
|
||||
.validateFields()
|
||||
.then(() => {
|
||||
if (!setupNewRouteHA || formRoute.peer != "") {
|
||||
const routeToSave = createRouteToSave(formRoute);
|
||||
if (routeToSave.peer && routeToSave.peer_groups?.length === 0) {
|
||||
delete routeToSave.peer_groups;
|
||||
}
|
||||
dispatch(
|
||||
routeActions.saveRoute.request({
|
||||
getAccessTokenSilently: getTokenSilently,
|
||||
@@ -413,7 +411,7 @@ const RouteAddNew = () => {
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Peer groups
|
||||
Peer group
|
||||
</label>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
|
||||
@@ -472,8 +472,6 @@ const SetupKeyNew = (props: any) => {
|
||||
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)}
|
||||
optionFilterProp="searchValue"
|
||||
>
|
||||
{tagGroups.map((m, index) => (
|
||||
|
||||
+23
-10
@@ -79,6 +79,7 @@ const UserEdit = (props: any) => {
|
||||
const [formUser, setFormUser] = useState({} as FormUser);
|
||||
const [form] = Form.useForm();
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [isOwner, setIsOwner] = useState(false);
|
||||
|
||||
const [confirmModal, confirmModalContextHolder] = Modal.useModal();
|
||||
|
||||
@@ -94,15 +95,21 @@ const UserEdit = (props: any) => {
|
||||
};
|
||||
|
||||
const createUserToSave = (values: any): UserToSave => {
|
||||
const autoGroups =
|
||||
groups
|
||||
?.filter((g) => values.autoGroupsNames.includes(g.id))
|
||||
.map((g) => g.id || "") || [];
|
||||
let autoGroups:string[] = []
|
||||
if (values.autoGroupsNames) {
|
||||
autoGroups =
|
||||
groups
|
||||
?.filter((g) => values.autoGroupsNames.includes(g.id))
|
||||
.map((g) => g.id || "") || [];
|
||||
}
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const allGroupsNames: string[] = groups?.map((g) => g.id || "");
|
||||
const groupsToCreate = values.autoGroupsNames.filter(
|
||||
(s: string) => !allGroupsNames.includes(s)
|
||||
);
|
||||
let groupsToCreate:string[] = []
|
||||
if (values.autoGroupsNames) {
|
||||
groupsToCreate = values.autoGroupsNames.filter(
|
||||
(s: string) => !allGroupsNames.includes(s)
|
||||
);
|
||||
}
|
||||
let userID = user ? user.id : "";
|
||||
let isServiceUser = user ? user?.is_service_user : false;
|
||||
return {
|
||||
@@ -120,7 +127,8 @@ const UserEdit = (props: any) => {
|
||||
if (users) {
|
||||
let currentUser = users.find((user) => user?.is_current);
|
||||
if (currentUser) {
|
||||
setIsAdmin(currentUser.role === "admin");
|
||||
setIsAdmin(currentUser.role === "admin" || currentUser.role === "owner");
|
||||
setIsOwner(currentUser.role === "owner");
|
||||
}
|
||||
}
|
||||
}, [users]);
|
||||
@@ -403,7 +411,7 @@ const UserEdit = (props: any) => {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
disabled={user?.is_current}
|
||||
disabled={user?.is_current || user?.role === "owner"}
|
||||
>
|
||||
<Option value="admin">
|
||||
<Text type={"secondary"}>admin</Text>
|
||||
@@ -411,6 +419,11 @@ const UserEdit = (props: any) => {
|
||||
<Option value="user">
|
||||
<Text type={"secondary"}>user</Text>
|
||||
</Option>
|
||||
{!user?.is_service_user && isOwner && (
|
||||
<Option value="owner">
|
||||
<Text type={"secondary"}>owner</Text>
|
||||
</Option>
|
||||
)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
@@ -473,7 +486,7 @@ const UserEdit = (props: any) => {
|
||||
label="Block user"
|
||||
style={{ marginRight: "50px", fontWeight: "500" }}
|
||||
>
|
||||
<Switch />
|
||||
<Switch disabled={user?.role == "owner"} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,8 @@ import MacTab from "./MacTab";
|
||||
import Link from "antd/lib/typography/Link";
|
||||
import DockerTab from "./DockerTab";
|
||||
import AndroidTab from "./AndroidTab";
|
||||
import IOSTab from "./IOSTab";
|
||||
import {IOSIcon} from "./IOSIcon";
|
||||
|
||||
type Props = {
|
||||
greeting?: string;
|
||||
@@ -54,11 +56,16 @@ export const AddPeerPopup: React.FC<Props> = ({
|
||||
},
|
||||
{
|
||||
key: "4",
|
||||
label: <span data-testid="add-peer-modal-ios-tab"><IOSIcon/>iOS</span>,
|
||||
children: <IOSTab/>,
|
||||
},
|
||||
{
|
||||
key: "5",
|
||||
label: <span data-testid="add-peer-modal-android-tab"><AndroidFilled/>Android</span>,
|
||||
children: <AndroidTab/>,
|
||||
},
|
||||
{
|
||||
key: "5",
|
||||
key: "6",
|
||||
label: <span data-testid="add-peer-modal-docker-tab"><Icon component={DockerSVG}/>Docker</span>,
|
||||
children: <DockerTab/>,
|
||||
}
|
||||
|
||||
Loaded 20 of 44 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user