Skip to content

Commit c88c3b1

Browse files
authored
Refactor several modals to functional components (#8748)
In this PR I converted several class components to functional components using modern React hooks - `TransferTaskModal` - `NewTaskDescriptionModal` - `RecommendedConfigurationModal` - `TreeRemovalModal` - `AddNewLayoutModal` - `UserScriptsModalView` ### Steps to test: - Check that the modals are still showing - The changes are lightweight enough to not do deep test ### Issues: - Contributes to #8747 ------ (Please delete unneeded items, merge only when none are left open) - [ ] 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
1 parent b01f062 commit c88c3b1

File tree

6 files changed

+281
-368
lines changed

6 files changed

+281
-368
lines changed

frontend/javascripts/dashboard/transfer_task_modal.tsx

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { transferTask } from "admin/api/tasks";
22
import UserSelectionComponent from "admin/user/user_selection_component";
33
import { Button, Modal } from "antd";
44
import { handleGenericError } from "libs/error_handling";
5-
import * as React from "react";
5+
import type React from "react";
6+
import { memo, useCallback, useState } from "react";
67
import type { APIAnnotation } from "types/api_types";
78

89
type Props = {
@@ -11,67 +12,53 @@ type Props = {
1112
onCancel: (...args: Array<any>) => any;
1213
isOpen: boolean;
1314
};
14-
type State = {
15-
currentUserIdValue: string;
16-
};
1715

18-
class TransferTaskModal extends React.PureComponent<Props, State> {
19-
state: State = {
20-
currentUserIdValue: "",
21-
};
16+
const TransferTaskModal: React.FC<Props> = ({ isOpen, onCancel, annotationId, onChange }) => {
17+
const [currentUserIdValue, setCurrentUserIdValue] = useState("");
2218

23-
async transfer() {
24-
const annotationId = this.props.annotationId;
19+
const handleSelectChange = useCallback((userId: string) => {
20+
setCurrentUserIdValue(userId);
21+
}, []);
2522

23+
const transfer = useCallback(async () => {
2624
if (!annotationId) {
2725
throw new Error("No annotation id provided");
2826
}
2927

3028
try {
31-
const updatedAnnotation = await transferTask(annotationId, this.state.currentUserIdValue);
32-
this.props.onChange(updatedAnnotation);
29+
const updatedAnnotation = await transferTask(annotationId, currentUserIdValue);
30+
onChange(updatedAnnotation);
31+
setCurrentUserIdValue("");
3332
} catch (error) {
3433
handleGenericError(error as Error);
3534
}
36-
}
35+
}, [annotationId, currentUserIdValue, onChange]);
3736

38-
handleSelectChange = (userId: string) => {
39-
this.setState({
40-
currentUserIdValue: userId,
41-
});
42-
};
43-
44-
render() {
45-
if (!this.props.isOpen) {
46-
return null;
47-
}
37+
if (!isOpen) {
38+
return null;
39+
}
4840

49-
return (
50-
<Modal
51-
title="Transfer a Task"
52-
open={this.props.isOpen}
53-
onCancel={this.props.onCancel}
54-
footer={
55-
<div>
56-
<Button
57-
type="primary"
58-
onClick={() => this.transfer()}
59-
disabled={this.state.currentUserIdValue === ""}
60-
>
61-
Transfer
62-
</Button>
63-
<Button onClick={() => this.props.onCancel()}>Close</Button>
64-
</div>
65-
}
66-
>
67-
<div className="control-group">
68-
<div className="form-group">
69-
<UserSelectionComponent handleSelection={this.handleSelectChange} />
70-
</div>
41+
return (
42+
<Modal
43+
title="Transfer a Task"
44+
open={isOpen}
45+
onCancel={onCancel}
46+
footer={() => (
47+
<>
48+
<Button type="primary" onClick={transfer} disabled={currentUserIdValue === ""}>
49+
Transfer
50+
</Button>
51+
<Button onClick={onCancel}>Close</Button>
52+
</>
53+
)}
54+
>
55+
<div className="control-group">
56+
<div className="form-group">
57+
<UserSelectionComponent handleSelection={handleSelectChange} />
7158
</div>
72-
</Modal>
73-
);
74-
}
75-
}
59+
</div>
60+
</Modal>
61+
);
62+
};
7663

77-
export default TransferTaskModal;
64+
export default memo(TransferTaskModal);
Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,36 @@
11
import { Input, Modal } from "antd";
2-
import * as React from "react";
2+
import type React from "react";
3+
import { memo, useCallback, useState } from "react";
34

45
type Props = {
56
addLayout: (arg0: string) => void;
67
isOpen: boolean;
78
onCancel: () => void;
89
};
9-
type State = {
10-
value: string;
11-
};
1210

13-
class AddNewLayoutModal extends React.PureComponent<Props, State> {
14-
state: State = {
15-
value: "",
16-
};
17-
onConfirm = () => {
18-
const value = this.state.value;
19-
this.setState({
20-
value: "",
21-
});
22-
this.props.addLayout(value);
23-
};
11+
const AddNewLayoutModal: React.FC<Props> = ({ addLayout, isOpen, onCancel }) => {
12+
const [value, setValue] = useState("");
13+
14+
const onConfirm = useCallback(() => {
15+
addLayout(value);
16+
setValue("");
17+
}, [addLayout, value]);
2418

25-
render() {
26-
return (
27-
<Modal
28-
title="Add a new layout"
29-
open={this.props.isOpen}
30-
onOk={this.onConfirm}
31-
onCancel={this.props.onCancel}
32-
>
33-
<Input
34-
placeholder="Layout Name"
35-
value={this.state.value}
36-
onChange={(evt) => {
37-
this.setState({
38-
value: evt.target.value,
39-
});
40-
}}
41-
autoFocus
42-
onPressEnter={this.onConfirm}
43-
/>
44-
</Modal>
45-
);
46-
}
47-
}
19+
const handleChange = useCallback((evt: React.ChangeEvent<HTMLInputElement>) => {
20+
setValue(evt.target.value);
21+
}, []);
22+
23+
return (
24+
<Modal title="Add a new layout" open={isOpen} onOk={onConfirm} onCancel={onCancel}>
25+
<Input
26+
placeholder="Layout Name"
27+
value={value}
28+
onChange={handleChange}
29+
autoFocus
30+
onPressEnter={onConfirm}
31+
/>
32+
</Modal>
33+
);
34+
};
4835

49-
export default AddNewLayoutModal;
36+
export default memo(AddNewLayoutModal);

0 commit comments

Comments
 (0)