Skip to content

Commit 8931a9d

Browse files
committed
frontend/i18n: change email-address-setting to an FC component, add a bit more translations; translate a bit of Chat
1 parent 8270138 commit 8931a9d

File tree

9 files changed

+295
-162
lines changed

9 files changed

+295
-162
lines changed

src/packages/frontend/account/settings/email-address-setting.tsx

Lines changed: 138 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { Component, Rendered, ReactDOM } from "../../app-framework";
7-
import { alert_message } from "../../alerts";
8-
import { log } from "../../user-tracking";
9-
import { ErrorDisplay, LabeledRow, Saving } from "../../components";
6+
import { FormattedMessage, useIntl } from "react-intl";
7+
8+
import { alert_message } from "@cocalc/frontend/alerts";
109
import {
1110
Button,
1211
ButtonToolbar,
13-
Well,
14-
FormGroup,
1512
FormControl,
16-
} from "../../antd-bootstrap";
17-
import { webapp_client } from "../../webapp-client";
13+
FormGroup,
14+
Well,
15+
} from "@cocalc/frontend/antd-bootstrap";
16+
import {
17+
ReactDOM,
18+
Rendered,
19+
useRef,
20+
useState,
21+
} from "@cocalc/frontend/app-framework";
22+
import { ErrorDisplay, LabeledRow, Saving } from "@cocalc/frontend/components";
23+
import { labels } from "@cocalc/frontend/i18n";
24+
import { log } from "@cocalc/frontend/user-tracking";
25+
import { webapp_client } from "@cocalc/frontend/webapp-client";
26+
import { COLORS } from "@cocalc/util/theme";
1827

1928
interface Props {
2029
account_id: string;
@@ -24,77 +33,59 @@ interface Props {
2433
verify_emails?: boolean;
2534
}
2635

27-
interface State {
28-
state: "view" | "edit" | "saving"; // view --> edit --> saving --> view or edit
29-
password: string;
30-
email_address: string; // The new email address
31-
error: string;
32-
}
36+
export const EmailAddressSetting = (props: Readonly<Props>) => {
37+
const intl = useIntl();
3338

34-
export class EmailAddressSetting extends Component<Props, State> {
35-
constructor(props, state) {
36-
super(props, state);
37-
this.state = { state: "view", password: "", email_address: "", error: "" };
38-
}
39+
const emailRef = useRef<FormControl>(null);
40+
const passwordRef = useRef<FormControl>(null);
41+
42+
const [state, setState] = useState<"view" | "edit" | "saving">("view");
43+
const [password, setPassword] = useState<string>("");
44+
const [email_address, set_email_address] = useState<string>("");
45+
const [error, setError] = useState<string>("");
3946

40-
private start_editing(): void {
41-
this.setState({
42-
state: "edit",
43-
email_address:
44-
this.props.email_address != null ? this.props.email_address : "",
45-
error: "",
46-
password: "",
47-
});
47+
function start_editing(): void {
48+
setState("edit");
49+
set_email_address(props.email_address != null ? props.email_address : "");
50+
setError("");
51+
setPassword("");
4852
}
4953

50-
private cancel_editing(): void {
51-
this.setState({
52-
state: "view",
53-
password: "",
54-
}); // more secure...
54+
function cancel_editing(): void {
55+
setState("view");
56+
setPassword("");
5557
}
5658

57-
private async save_editing(): Promise<void> {
58-
if (this.state.password.length < 6) {
59-
this.setState({
60-
state: "edit",
61-
error: "Password must be at least 6 characters long.",
62-
});
59+
async function save_editing(): Promise<void> {
60+
if (password.length < 6) {
61+
setState("edit");
62+
setError("Password must be at least 6 characters long.");
6363
return;
6464
}
65-
this.setState({
66-
state: "saving",
67-
});
65+
setState("saving");
6866
try {
69-
await webapp_client.account_client.change_email(
70-
this.state.email_address,
71-
this.state.password
72-
);
67+
await webapp_client.account_client.change_email(email_address, password);
7368
} catch (error) {
74-
this.setState({
75-
state: "edit",
76-
error: `Error -- ${error}`,
77-
});
69+
setState("edit");
70+
setError(`Error -- ${error}`);
7871
return;
7972
}
80-
if (this.props.is_anonymous) {
73+
if (props.is_anonymous) {
8174
log("email_sign_up", { source: "anonymous_account" });
8275
}
83-
this.setState({
84-
state: "view",
85-
error: "",
86-
password: "",
87-
});
76+
setState("view");
77+
setError("");
78+
setPassword("");
8879
// if email verification is enabled, send out a token
8980
// in any case, send a welcome email to an anonymous user, possibly
9081
// including an email verification link
91-
if (!(this.props.verify_emails || this.props.is_anonymous)) {
82+
if (!(props.verify_emails || props.is_anonymous)) {
9283
return;
9384
}
9485
try {
9586
// anonymouse users will get the "welcome" email
9687
await webapp_client.account_client.send_verification_email(
97-
!this.props.is_anonymous
88+
!props.is_anonymous,
9889
);
9990
} catch (error) {
10091
const err_msg = `Problem sending welcome email: ${error}`;
@@ -103,141 +94,150 @@ export class EmailAddressSetting extends Component<Props, State> {
10394
}
10495
}
10596

106-
private is_submittable(): boolean {
107-
return !!(
108-
this.state.password !== "" &&
109-
this.state.email_address !== this.props.email_address
110-
);
97+
function is_submittable(): boolean {
98+
return !!(password !== "" && email_address !== props.email_address);
11199
}
112100

113-
private render_change_button(): Rendered {
101+
function render_change_button(): Rendered {
114102
return (
115103
<Button
116-
disabled={!this.is_submittable()}
117-
onClick={this.save_editing.bind(this)}
104+
disabled={!is_submittable()}
105+
onClick={save_editing}
118106
bsStyle="success"
119107
>
120-
{this.button_label()}
108+
{button_label()}
121109
</Button>
122110
);
123111
}
124112

125-
private render_error(): Rendered {
126-
if (this.state.error) {
113+
function render_error(): Rendered {
114+
if (error) {
127115
return (
128116
<ErrorDisplay
129-
error={this.state.error}
130-
onClose={() => this.setState({ error: "" })}
117+
error={error}
118+
onClose={() => setError("")}
131119
style={{ marginTop: "15px" }}
132120
/>
133121
);
134122
}
135123
}
136124

137-
private render_edit(): Rendered {
138-
const password_label = this.props.email_address
139-
? "Current password"
140-
: "Choose a password";
125+
function render_edit(): Rendered {
126+
const password_label = intl.formatMessage(
127+
{
128+
id: "account.settings.email_address.password_label",
129+
defaultMessage:
130+
"{have_email, select, true {Current password} other {Choose a password}}",
131+
},
132+
{
133+
have_email: !!props.email_address,
134+
},
135+
);
141136
return (
142137
<Well style={{ marginTop: "3ex" }}>
143138
<FormGroup>
144-
New email address
139+
<FormattedMessage
140+
id="account.settings.email_address.new_email_address_label"
141+
defaultMessage="New email address"
142+
/>
145143
<FormControl
146144
autoFocus
147145
type="email_address"
148-
ref="email_address"
149-
value={this.state.email_address}
146+
ref={emailRef}
147+
value={email_address}
150148
placeholder="[email protected]"
151-
onChange={() =>
152-
this.setState({
153-
email_address: ReactDOM.findDOMNode(this.refs.email_address)
154-
.value,
155-
})
156-
}
149+
onChange={() => {
150+
const em = ReactDOM.findDOMNode(emailRef.current)?.value;
151+
set_email_address(em);
152+
}}
157153
maxLength={254}
158154
/>
159155
</FormGroup>
160156
{password_label}
161157
<form
162158
onSubmit={(e) => {
163159
e.preventDefault();
164-
if (this.is_submittable()) {
165-
return this.save_editing();
160+
if (is_submittable()) {
161+
return save_editing();
166162
}
167163
}}
168164
>
169165
<FormGroup>
170166
<FormControl
171167
type="password"
172-
ref="password"
173-
value={this.state.password}
168+
ref={passwordRef}
169+
value={password}
174170
placeholder={password_label}
175171
onChange={() => {
176-
const password = ReactDOM.findDOMNode(
177-
this.refs.password
178-
)?.value;
179-
if (password != null) {
180-
this.setState({
181-
password,
182-
});
172+
const pw = ReactDOM.findDOMNode(passwordRef.current)?.value;
173+
if (pw != null) {
174+
setPassword(pw);
183175
}
184176
}}
185177
/>
186178
</FormGroup>
187179
</form>
188180
<ButtonToolbar>
189-
{this.render_change_button()}
190-
<Button onClick={this.cancel_editing.bind(this)}>Cancel</Button>
181+
{render_change_button()}
182+
<Button onClick={cancel_editing}>Cancel</Button>
191183
</ButtonToolbar>
192-
{this.render_error()}
193-
{this.render_saving()}
184+
{render_error()}
185+
{render_saving()}
194186
</Well>
195187
);
196188
}
197189

198-
private render_saving(): Rendered {
199-
if (this.state.state === "saving") {
190+
function render_saving(): Rendered {
191+
if (state === "saving") {
200192
return <Saving />;
201193
}
202194
}
203195

204-
private button_label(): string {
205-
if (this.props.is_anonymous) {
206-
return "Sign up using an email address and password";
207-
} else if (this.props.email_address) {
208-
return "Change email address";
209-
} else {
210-
return "Set email address and password";
211-
}
212-
}
213-
214-
public render(): Rendered {
215-
const label = this.props.is_anonymous ? (
216-
<h5 style={{ color: "#666" }}>
217-
Sign up using an email address and password
218-
</h5>
219-
) : (
220-
"Email address"
221-
);
222-
return (
223-
<LabeledRow
224-
label={label}
225-
style={this.props.disabled ? { color: "#666" } : undefined}
226-
>
227-
<div>
228-
{this.props.email_address}
229-
{this.state.state === "view" ? (
230-
<Button
231-
disabled={this.props.disabled}
232-
className="pull-right"
233-
onClick={this.start_editing.bind(this)}
234-
>
235-
{this.button_label()}...
236-
</Button>
237-
) : undefined}
238-
</div>
239-
{this.state.state !== "view" ? this.render_edit() : undefined}
240-
</LabeledRow>
196+
function button_label(): string {
197+
return intl.formatMessage(
198+
{
199+
id: "account.settings.email_address.button_label",
200+
defaultMessage: `{type, select,
201+
anonymous {Sign up using an email address and password}
202+
have_email {Change email address}
203+
other {Set email address and password}}`,
204+
},
205+
{
206+
type: props.is_anonymous
207+
? "anonymous"
208+
: props.email_address
209+
? "have_email"
210+
: "",
211+
},
241212
);
242213
}
243-
}
214+
215+
const label = props.is_anonymous ? (
216+
<h5 style={{ color: COLORS.GRAY_M }}>
217+
Sign up using an email address and password
218+
</h5>
219+
) : (
220+
intl.formatMessage(labels.email_address)
221+
);
222+
223+
return (
224+
<LabeledRow
225+
label={label}
226+
style={props.disabled ? { color: COLORS.GRAY_M } : undefined}
227+
>
228+
<div>
229+
{props.email_address}
230+
{state === "view" ? (
231+
<Button
232+
disabled={props.disabled}
233+
className="pull-right"
234+
onClick={start_editing}
235+
>
236+
{button_label()}...
237+
</Button>
238+
) : undefined}
239+
</div>
240+
{state !== "view" ? render_edit() : undefined}
241+
</LabeledRow>
242+
);
243+
};

0 commit comments

Comments
 (0)