Skip to content

Commit 9367076

Browse files
committed
WIP account setting sub page styling
1 parent 58c2d49 commit 9367076

File tree

4 files changed

+145
-110
lines changed

4 files changed

+145
-110
lines changed

frontend/javascripts/admin/auth/account_settings_view.tsx

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,38 @@ import ProfileView from "./profile_view";
77

88
const { Sider, Content } = Layout;
99

10-
function PasskeysSettings() {
11-
return (
12-
<div>
13-
<h2>Passkeys</h2>
14-
<p>Passkeys settings page content will be added here.</p>
15-
</div>
16-
);
17-
}
18-
1910
function AccountSettingsView() {
2011
const location = useLocation();
2112
const history = useHistory();
2213
const selectedKey = location.pathname.split("/").pop() || "profile";
2314

2415
const menuItems = [
2516
{
26-
key: "profile",
27-
icon: <UserOutlined />,
28-
label: "Profile",
29-
},
30-
{
31-
key: "password",
32-
icon: <LockOutlined />,
33-
label: "Password",
34-
},
35-
{
36-
key: "passkeys",
37-
icon: <SafetyOutlined />,
38-
label: "Passkeys",
17+
label: "Account",
18+
type: "group",
19+
children: [
20+
{
21+
key: "profile",
22+
icon: <UserOutlined />,
23+
label: "Profile",
24+
},
25+
{
26+
key: "password",
27+
icon: <SafetyOutlined />,
28+
label: "Password",
29+
},
30+
],
3931
},
4032
{
41-
key: "token",
42-
icon: <SettingOutlined />,
43-
label: "Auth Token",
33+
label: "Developer",
34+
type: "group",
35+
children: [
36+
{
37+
key: "token",
38+
icon: <SettingOutlined />,
39+
label: "Auth Token",
40+
},
41+
],
4442
},
4543
];
4644

@@ -61,7 +59,6 @@ function AccountSettingsView() {
6159
<Switch>
6260
<Route path="/account/profile" component={ProfileView} />
6361
<Route path="/account/password" component={ChangePasswordView} />
64-
<Route path="/account/passkeys" component={PasskeysSettings} />
6562
<Route path="/account/token" component={AuthTokenView} />
6663
<Route path="/account" component={ProfileView} />
6764
</Switch>

frontend/javascripts/admin/auth/auth_token_view.tsx

Lines changed: 56 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { CopyOutlined, SwapOutlined } from "@ant-design/icons";
1+
import Icon, { CopyOutlined, InfoCircleOutlined, SwapOutlined } from "@ant-design/icons";
22
import { getAuthToken, revokeAuthToken } from "admin/rest_api";
3-
import { Button, Col, Form, Input, Row, Space, Spin } from "antd";
3+
import { Button, Typography, Descriptions, Form, Input, Row, Space, Spin, Popover } from "antd";
44
import { useWkSelector } from "libs/react_hooks";
55
import Toast from "libs/toast";
66
import { useEffect, useState } from "react";
7-
const FormItem = Form.Item;
7+
import { AccountSettingTitle } from "./profile_view";
8+
9+
const { Text } = Typography;
810

911
function AuthTokenView() {
1012
const activeUser = useWkSelector((state) => state.activeUser);
1113
const [isLoading, setIsLoading] = useState<boolean>(true);
1214
const [currentToken, setCurrentToken] = useState<string>("");
13-
const [form] = Form.useForm();
15+
1416
useEffect(() => {
1517
fetchData();
1618
}, []);
@@ -44,65 +46,58 @@ function AuthTokenView() {
4446
}
4547
};
4648

49+
const APIitems = [
50+
{
51+
label: "Auth Token",
52+
children: (
53+
<Text code copyable>
54+
{currentToken}
55+
</Text>
56+
),
57+
},
58+
{
59+
label: (
60+
<>
61+
<span className="icon-margin-right">Token Revocation</span>
62+
<Popover
63+
content="Revoke your token if it has been compromised or if you suspect someone else has gained
64+
access to it. This will invalidate all active sessions."
65+
>
66+
<InfoCircleOutlined />
67+
</Popover>
68+
</>
69+
),
70+
children: (
71+
<Button icon={<SwapOutlined />} onClick={handleRevokeToken}>
72+
Revoke and Generate New Token
73+
</Button>
74+
),
75+
},
76+
activeUser
77+
? {
78+
label: "Organization ID",
79+
children: (
80+
<Text code copyable>
81+
{activeUser.organization}
82+
</Text>
83+
),
84+
}
85+
: null,
86+
{
87+
label: "API Documentation",
88+
children: <a href="https://docs.webknossos.org/webknossos-py/index.html">Read the docs</a>,
89+
},
90+
];
91+
4792
return (
4893
<div>
49-
<h2>API Authentication</h2>
50-
<Row>
51-
<Col span={8}>
52-
<Spin size="large" spinning={isLoading}>
53-
<h4>Auth Token</h4>
54-
<Form form={form}>
55-
<FormItem>
56-
<Space.Compact>
57-
<Input
58-
value={currentToken}
59-
style={{
60-
width: "90%",
61-
}}
62-
readOnly
63-
/>
64-
<Button onClick={copyTokenToClipboard} icon={<CopyOutlined />} />
65-
</Space.Compact>
66-
</FormItem>
67-
<FormItem>
68-
<Button icon={<SwapOutlined />} onClick={handleRevokeToken}>
69-
Revoke Token
70-
</Button>
71-
</FormItem>
72-
</Form>
73-
{activeUser != null && (
74-
<>
75-
<h4>Organization ID</h4>
76-
<Form>
77-
<FormItem>
78-
<Space.Compact>
79-
<Input
80-
value={activeUser.organization}
81-
style={{
82-
width: "90%",
83-
}}
84-
readOnly
85-
/>
86-
<Button onClick={copyOrganizationIdToClipboard} icon={<CopyOutlined />} />
87-
</Space.Compact>
88-
</FormItem>
89-
</Form>
90-
</>
91-
)}
92-
</Spin>
93-
94-
<p>
95-
Your Auth Token is a unique string of characters that authenticates you when using our
96-
<a href="https://docs.webknossos.org/webknossos-py/index.html"> Python API</a>. It is
97-
request to verify your identity.
98-
</p>
99-
<p>
100-
Revoke your token if it has been compromised or if you suspect someone else has gained
101-
access to it.
102-
<a href="https://docs.webknossos.org/webknossos-py/index.html">Read more</a>
103-
</p>
104-
</Col>
105-
</Row>
94+
<AccountSettingTitle
95+
title="API Authorization"
96+
description="Access the WEBKNOSSO Python API with your API token"
97+
/>
98+
<Spin size="large" spinning={isLoading}>
99+
<Descriptions column={2} layout="vertical" colon={false} items={APIitems} />
100+
</Spin>
106101
</div>
107102
);
108103
}

frontend/javascripts/admin/auth/change_password_view.tsx

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { LockOutlined } from "@ant-design/icons";
2-
import { Alert, Button, Col, Form, Input, Row } from "antd";
2+
import { Alert, Button, Col, Descriptions, Form, Input, Row, Space } from "antd";
33
import Request from "libs/request";
44
import Toast from "libs/toast";
55
import messages from "messages";
66
import { type RouteComponentProps, withRouter } from "react-router-dom";
77
import { logoutUserAction } from "viewer/model/actions/user_actions";
88
import Store from "viewer/store";
9+
import { AccountSettingTitle } from "./profile_view";
910
const FormItem = Form.Item;
1011
const { Password } = Input;
1112

@@ -44,9 +45,41 @@ function ChangePasswordView({ history }: Props) {
4445
return Promise.resolve();
4546
}
4647

48+
const items = [
49+
{
50+
label: "Password",
51+
children: (
52+
<>
53+
<Space.Compact>
54+
<Input.Password
55+
prefix={
56+
<LockOutlined
57+
style={{
58+
fontSize: 13,
59+
}}
60+
/>
61+
}
62+
value="***************"
63+
/>
64+
<Button
65+
type="primary"
66+
htmlType="submit"
67+
style={{
68+
width: "100%",
69+
}}
70+
>
71+
Change Password
72+
</Button>
73+
</Space.Compact>
74+
</>
75+
),
76+
},
77+
];
78+
4779
return (
4880
<div>
49-
<h2>Password</h2>
81+
<AccountSettingTitle title="Password" description="Manage and update your password" />
82+
<Descriptions column={2} layout="vertical" colon={false} items={items} />
5083
<Row>
5184
<Col span={8}>
5285
<Form onFinish={onFinish} form={form}>
@@ -144,12 +177,13 @@ function ChangePasswordView({ history }: Props) {
144177
width: "100%",
145178
}}
146179
>
147-
Change Password
180+
Update Password
148181
</Button>
149182
</FormItem>
150183
</Form>
151184
</Col>
152185
</Row>
186+
<AccountSettingTitle title="Passkeys" description="Login passwordless with Passkeys" />
153187
</div>
154188
);
155189
}

frontend/javascripts/admin/auth/profile_view.tsx

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ import { setThemeAction } from "viewer/model/actions/ui_actions";
1212

1313
const { Title, Text } = Typography;
1414

15+
export function AccountSettingTitle({
16+
title,
17+
description,
18+
}: { title: string; description: string }) {
19+
return (
20+
<div>
21+
<h2 style={{ marginBottom: 0 }}>{title}</h2>
22+
<Text type="secondary" style={{ display: "block" }}>
23+
{description}
24+
</Text>
25+
<Divider style={{ margin: "12px 0 32px 0" }} />
26+
</div>
27+
);
28+
}
29+
1530
function ProfileView() {
1631
const activeUser = useWkSelector((state) => state.activeUser);
1732
const activeOrganization = useWkSelector((state) => state.activeOrganization);
@@ -76,32 +91,26 @@ function ProfileView() {
7691
{
7792
label: "Theme",
7893
children: (
79-
<Dropdown menu={{ items: themeItems }} trigger={["click"]}>
80-
<Text>
81-
{themeItems.find((item) => item.key === selectedTheme)?.label} <DownOutlined />
82-
</Text>
83-
</Dropdown>
94+
<Dropdown.Button menu={{ items: themeItems }} trigger={["click"]} icon={<DownOutlined />}>
95+
{themeItems.find((item) => item.key === selectedTheme)?.label}
96+
</Dropdown.Button>
8497
),
8598
},
8699
];
87100

88101
return (
89102
<div>
90-
<Title level={2}>Profile</Title>
91-
<Text type="secondary" style={{ display: "block", marginBottom: 24 }}>
92-
Manage your personal information and preferences
93-
</Text>
94-
<Divider />
95-
<Card>
96-
<Card.Meta title="Profile" description="Manage your personal information and preferences" />
97-
<Descriptions
98-
column={2}
99-
colon={false}
100-
layout="vertical"
101-
style={{ marginBottom: 24 }}
102-
items={profileItems}
103-
/>
104-
</Card>
103+
<AccountSettingTitle
104+
title="Profile"
105+
description="Manage your personal information and preferences"
106+
/>
107+
<Descriptions
108+
column={2}
109+
colon={false}
110+
layout="vertical"
111+
style={{ marginBottom: 24 }}
112+
items={profileItems}
113+
/>
105114
</div>
106115
);
107116
}

0 commit comments

Comments
 (0)