Skip to content

Commit 91e81ee

Browse files
Dataset Settings: Refactor as React functional components (#8719)
In preparation of restyling this component in a similar fashion as the account and organization settings, I first refactored several datasets settings & tab components as React functional components to use modern hook APIs etc. I move the beforeUnload into it's own hook. This might be related to issue #5977 ### URL of deployed dev instance (used for testing): - https://functionaldatasetsettings.webknossos.xyz/ ### Issues: - Related to #8672 ------ (Please delete unneeded items, merge only when none are left open) - [x] Added changelog entry (create a `$PR_NUMBER.md` file in `unreleased_changes` or use `./tools/create-changelog-entry.py`) - [ ] Added migration guide entry if applicable (edit the same file as for the changelog) - [ ] Updated [documentation](../blob/master/docs) if applicable - [ ] Adapted [wk-libs python client](https://github.com/scalableminds/webknossos-libs/tree/master/webknossos/webknossos/client) if relevant API parts change - [ ] Removed dev-only changes like prints and application.conf edits - [ ] Considered [common edge cases](../blob/master/.github/common_edge_cases.md) - [ ] Needs datastore update after deployment --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 1b86c7b commit 91e81ee

32 files changed

+1912
-1838
lines changed

frontend/javascripts/admin/account/account_auth_token_view.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button, Col, Row, Spin, Typography } from "antd";
44
import { useWkSelector } from "libs/react_hooks";
55
import Toast from "libs/toast";
66
import { useEffect, useState } from "react";
7-
import { SettingsCard } from "./helpers/settings_card";
7+
import { SettingsCard, type SettingsCardProps } from "./helpers/settings_card";
88
import { SettingsTitle } from "./helpers/settings_title";
99

1010
const { Text } = Typography;
@@ -41,20 +41,20 @@ function AccountAuthTokenView() {
4141
}
4242
};
4343

44-
const APIitems = [
44+
const APIitems: SettingsCardProps[] = [
4545
{
4646
title: "Auth Token",
47-
value: (
47+
content: (
4848
<Text code copyable>
4949
{currentToken}
5050
</Text>
5151
),
5252
},
5353
{
5454
title: "Token Revocation",
55-
explanation:
55+
tooltip:
5656
"Revoke your token if it has been compromised or if you suspect someone else has gained access to it. This will invalidate all active sessions.",
57-
value: (
57+
content: (
5858
<Button icon={<SwapOutlined />} type="primary" ghost onClick={handleRevokeToken}>
5959
Revoke and Generate New Token
6060
</Button>
@@ -64,7 +64,7 @@ function AccountAuthTokenView() {
6464
? [
6565
{
6666
title: "Organization ID",
67-
value: (
67+
content: (
6868
<Text code copyable>
6969
{activeUser.organization}
7070
</Text>
@@ -74,7 +74,7 @@ function AccountAuthTokenView() {
7474
: []),
7575
{
7676
title: "API Documentation",
77-
value: (
77+
content: (
7878
<a href="https://docs.webknossos.org/webknossos-py/index.html">
7979
Read the docs <ExportOutlined />
8080
</a>
@@ -92,11 +92,7 @@ function AccountAuthTokenView() {
9292
<Row gutter={[24, 24]} style={{ marginBottom: 24 }}>
9393
{APIitems.map((item) => (
9494
<Col span={12} key={item.title}>
95-
<SettingsCard
96-
title={item.title}
97-
description={item.value}
98-
explanation={item.explanation}
99-
/>
95+
<SettingsCard title={item.title} content={item.content} tooltip={item.tooltip} />
10096
</Col>
10197
))}
10298
</Row>

frontend/javascripts/admin/account/account_password_view.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useState } from "react";
77
import { useNavigate } from "react-router-dom";
88
import { logoutUserAction } from "viewer/model/actions/user_actions";
99
import Store from "viewer/store";
10-
import { SettingsCard } from "./helpers/settings_card";
10+
import { SettingsCard, type SettingsCardProps } from "./helpers/settings_card";
1111
import { SettingsTitle } from "./helpers/settings_title";
1212
const FormItem = Form.Item;
1313
const { Password } = Input;
@@ -155,10 +155,10 @@ function AccountPasswordView() {
155155
setResetPasswordVisible(true);
156156
}
157157

158-
const passKeyList = [
158+
const passKeyList: SettingsCardProps[] = [
159159
{
160160
title: "Coming soon",
161-
value: "Passwordless login with passkeys is coming soon",
161+
content: "Passwordless login with passkeys is coming soon",
162162
// action: <Button type="default" shape="circle" icon={<DeleteOutlined />} size="small" />,
163163
action: undefined,
164164
},
@@ -171,7 +171,7 @@ function AccountPasswordView() {
171171
<Col span={12}>
172172
<SettingsCard
173173
title="Password"
174-
description={getPasswordComponent()}
174+
content={getPasswordComponent()}
175175
action={
176176
<Button
177177
type="default"
@@ -189,7 +189,7 @@ function AccountPasswordView() {
189189
<Row gutter={[24, 24]} style={{ marginBottom: 24 }}>
190190
{passKeyList.map((item) => (
191191
<Col span={12} key={item.title}>
192-
<SettingsCard title={item.title} description={item.value} action={item.action} />
192+
<SettingsCard title={item.title} content={item.content} action={item.action} />
193193
</Col>
194194
))}
195195
</Row>

frontend/javascripts/admin/account/account_profile_view.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { formatUserName } from "viewer/model/accessors/user_accessor";
99
import { setThemeAction } from "viewer/model/actions/ui_actions";
1010
import { setActiveUserAction } from "viewer/model/actions/user_actions";
1111
import Store from "viewer/store";
12-
import { SettingsCard } from "./helpers/settings_card";
12+
import { SettingsCard, type SettingsCardProps } from "./helpers/settings_card";
1313
import { SettingsTitle } from "./helpers/settings_title";
1414

1515
function AccountProfileView() {
@@ -56,29 +56,29 @@ function AccountProfileView() {
5656
},
5757
];
5858

59-
const profileItems = [
59+
const profileItems: SettingsCardProps[] = [
6060
{
6161
title: "Name",
62-
value: formatUserName(activeUser, activeUser),
62+
content: formatUserName(activeUser, activeUser),
6363
},
6464
{
6565
title: "Email",
66-
value: activeUser.email,
66+
content: activeUser.email,
6767
},
6868
{
6969
title: "Organization",
70-
value: activeOrganization?.name || activeUser.organization,
70+
content: activeOrganization?.name || activeUser.organization,
7171
},
7272
{
7373
title: "Role",
74-
value: role,
75-
explanation: (
74+
content: role,
75+
tooltip: (
7676
<a href="https://docs.webknossos.org/webknossos/users/access_rights.html">Learn More</a>
7777
),
7878
},
7979
{
8080
title: "Theme",
81-
value: (
81+
content: (
8282
<Dropdown.Button menu={{ items: themeItems }} trigger={["click"]} icon={<DownOutlined />}>
8383
{themeItems.find((item) => item.key === selectedTheme)?.label}
8484
</Dropdown.Button>
@@ -95,11 +95,7 @@ function AccountProfileView() {
9595
<Row gutter={[24, 24]} style={{ marginBottom: 24 }}>
9696
{profileItems.map((item) => (
9797
<Col span={12} key={item.title}>
98-
<SettingsCard
99-
title={item.title}
100-
description={item.value}
101-
explanation={item.explanation}
102-
/>
98+
<SettingsCard title={item.title} content={item.content} tooltip={item.tooltip} />
10399
</Col>
104100
))}
105101
</Row>

frontend/javascripts/admin/account/account_settings_view.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ const MENU_ITEMS: MenuItemGroupType[] = [
4444
function AccountSettingsView() {
4545
const location = useLocation();
4646
const navigate = useNavigate();
47-
const selectedKey = location.pathname.split("/").filter(Boolean).pop() || "profile";
47+
const selectedKey =
48+
location.pathname
49+
.split("/")
50+
.filter((p) => p.length > 0)
51+
.pop() || "profile";
4852

4953
const breadcrumbItems = [
5054
{
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
import { InfoCircleOutlined } from "@ant-design/icons";
2-
import { Card, Flex, Popover, Typography } from "antd";
2+
import { Card, Flex, Tooltip, Typography } from "antd";
33

4-
interface SettingsCardProps {
4+
export type SettingsCardProps = {
55
title: string;
6-
description: React.ReactNode;
7-
explanation?: React.ReactNode;
6+
content: React.ReactNode;
7+
tooltip?: React.ReactNode;
88
action?: React.ReactNode;
9-
}
9+
style?: React.CSSProperties;
10+
};
1011

11-
export function SettingsCard({ title, description, explanation, action }: SettingsCardProps) {
12+
export function SettingsCard({ title, content, tooltip, action, style }: SettingsCardProps) {
1213
return (
13-
<Card style={{ minHeight: 105 }}>
14+
<Card style={{ minHeight: 105, ...style }}>
1415
<Typography.Text type="secondary" style={{ fontSize: 14 }}>
1516
<Flex justify="space-between">
1617
<div>
1718
{title}
1819

19-
{explanation != null ? (
20-
<Popover content={explanation}>
21-
<InfoCircleOutlined style={{ marginLeft: 4 }} />
22-
</Popover>
20+
{tooltip != null ? (
21+
<Tooltip title={tooltip}>
22+
<InfoCircleOutlined style={{ marginLeft: 8 }} />
23+
</Tooltip>
2324
) : null}
2425
</div>
2526
{action}
2627
</Flex>
2728
</Typography.Text>
28-
<div style={{ fontSize: 16, marginTop: 4 }}>{description}</div>
29+
<div style={{ fontSize: 16, marginTop: 4 }}>{content}</div>
2930
</Card>
3031
);
3132
}

0 commit comments

Comments
 (0)